xref: /dragonfly/sys/bus/u4b/usb_pf.c (revision 38b930d0)
1 /*-
2  * Copyright (c) 1990, 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from the Stanford/CMU enet packet filter,
6  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
7  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
8  * Berkeley Laboratory.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/bus.h>
38 #include <sys/fcntl.h>
39 #include <sys/malloc.h>
40 #include <sys/proc.h>
41 #include <sys/socket.h>
42 #include <sys/sockio.h>
43 #include <net/if.h>
44 #include <net/if_types.h>
45 #include <net/bpf.h>
46 #include <sys/sysctl.h>
47 #include <sys/condvar.h>
48 
49 #include <bus/u4b/usb.h>
50 #include <bus/u4b/usbdi.h>
51 #include <bus/u4b/usb_busdma.h>
52 #include <bus/u4b/usb_controller.h>
53 #include <bus/u4b/usb_core.h>
54 #include <bus/u4b/usb_process.h>
55 #include <bus/u4b/usb_device.h>
56 #include <bus/u4b/usb_bus.h>
57 #include <bus/u4b/usb_pf.h>
58 #include <bus/u4b/usb_transfer.h>
59 
60 static int usb_no_pf;
61 
62 SYSCTL_INT(_hw_usb, OID_AUTO, no_pf, CTLFLAG_RW,
63     &usb_no_pf, 0, "Set to disable USB packet filtering");
64 
65 TUNABLE_INT("hw.usb.no_pf", &usb_no_pf);
66 
67 void
68 usbpf_attach(struct usb_bus *ubus)
69 {
70 	struct ifnet *ifp;
71 
72 	if (usb_no_pf != 0) {
73 		ubus->ifp = NULL;
74 		return;
75 	}
76 
77 	ifp = ubus->ifp = if_alloc(IFT_USB);
78 	if (ifp == NULL) {
79 		device_printf(ubus->parent, "usbpf: Could not allocate "
80 		    "instance\n");
81 		return;
82 	}
83 
84 	if_initname(ifp, "usbus", device_get_unit(ubus->bdev));
85 	ifp->if_flags = IFF_CANTCONFIG;
86 	if_attach(ifp);
87 	if_up(ifp);
88 
89 	/*
90 	 * XXX According to the specification of DLT_USB, it indicates
91 	 * packets beginning with USB setup header. But not sure all
92 	 * packets would be.
93 	 */
94 	bpfattach(ifp, DLT_USB, USBPF_HDR_LEN);
95 
96 	if (bootverbose)
97 		device_printf(ubus->parent, "usbpf: Attached\n");
98 }
99 
100 void
101 usbpf_detach(struct usb_bus *ubus)
102 {
103 	struct ifnet *ifp = ubus->ifp;
104 
105 	if (ifp != NULL) {
106 		bpfdetach(ifp);
107 		if_down(ifp);
108 		if_detach(ifp);
109 		if_free(ifp);
110 	}
111 	ubus->ifp = NULL;
112 }
113 
114 static uint32_t
115 usbpf_aggregate_xferflags(struct usb_xfer_flags *flags)
116 {
117 	uint32_t val = 0;
118 
119 	if (flags->force_short_xfer == 1)
120 		val |= USBPF_FLAG_FORCE_SHORT_XFER;
121 	if (flags->short_xfer_ok == 1)
122 		val |= USBPF_FLAG_SHORT_XFER_OK;
123 	if (flags->short_frames_ok == 1)
124 		val |= USBPF_FLAG_SHORT_FRAMES_OK;
125 	if (flags->pipe_bof == 1)
126 		val |= USBPF_FLAG_PIPE_BOF;
127 	if (flags->proxy_buffer == 1)
128 		val |= USBPF_FLAG_PROXY_BUFFER;
129 	if (flags->ext_buffer == 1)
130 		val |= USBPF_FLAG_EXT_BUFFER;
131 	if (flags->manual_status == 1)
132 		val |= USBPF_FLAG_MANUAL_STATUS;
133 	if (flags->no_pipe_ok == 1)
134 		val |= USBPF_FLAG_NO_PIPE_OK;
135 	if (flags->stall_pipe == 1)
136 		val |= USBPF_FLAG_STALL_PIPE;
137 	return (val);
138 }
139 
140 static uint32_t
141 usbpf_aggregate_status(struct usb_xfer_flags_int *flags)
142 {
143 	uint32_t val = 0;
144 
145 	if (flags->open == 1)
146 		val |= USBPF_STATUS_OPEN;
147 	if (flags->transferring == 1)
148 		val |= USBPF_STATUS_TRANSFERRING;
149 	if (flags->did_dma_delay == 1)
150 		val |= USBPF_STATUS_DID_DMA_DELAY;
151 	if (flags->did_close == 1)
152 		val |= USBPF_STATUS_DID_CLOSE;
153 	if (flags->draining == 1)
154 		val |= USBPF_STATUS_DRAINING;
155 	if (flags->started == 1)
156 		val |= USBPF_STATUS_STARTED;
157 	if (flags->bandwidth_reclaimed == 1)
158 		val |= USBPF_STATUS_BW_RECLAIMED;
159 	if (flags->control_xfr == 1)
160 		val |= USBPF_STATUS_CONTROL_XFR;
161 	if (flags->control_hdr == 1)
162 		val |= USBPF_STATUS_CONTROL_HDR;
163 	if (flags->control_act == 1)
164 		val |= USBPF_STATUS_CONTROL_ACT;
165 	if (flags->control_stall == 1)
166 		val |= USBPF_STATUS_CONTROL_STALL;
167 	if (flags->short_frames_ok == 1)
168 		val |= USBPF_STATUS_SHORT_FRAMES_OK;
169 	if (flags->short_xfer_ok == 1)
170 		val |= USBPF_STATUS_SHORT_XFER_OK;
171 #if USB_HAVE_BUSDMA
172 	if (flags->bdma_enable == 1)
173 		val |= USBPF_STATUS_BDMA_ENABLE;
174 	if (flags->bdma_no_post_sync == 1)
175 		val |= USBPF_STATUS_BDMA_NO_POST_SYNC;
176 	if (flags->bdma_setup == 1)
177 		val |= USBPF_STATUS_BDMA_SETUP;
178 #endif
179 	if (flags->isochronous_xfr == 1)
180 		val |= USBPF_STATUS_ISOCHRONOUS_XFR;
181 	if (flags->curr_dma_set == 1)
182 		val |= USBPF_STATUS_CURR_DMA_SET;
183 	if (flags->can_cancel_immed == 1)
184 		val |= USBPF_STATUS_CAN_CANCEL_IMMED;
185 	if (flags->doing_callback == 1)
186 		val |= USBPF_STATUS_DOING_CALLBACK;
187 
188 	return (val);
189 }
190 
191 static int
192 usbpf_xfer_frame_is_read(struct usb_xfer *xfer, uint32_t frame)
193 {
194 	int isread;
195 
196 	if ((frame == 0) && (xfer->flags_int.control_xfr != 0) &&
197 	    (xfer->flags_int.control_hdr != 0)) {
198 		/* special case */
199 		if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
200 			/* The device controller writes to memory */
201 			isread = 1;
202 		} else {
203 			/* The host controller reads from memory */
204 			isread = 0;
205 		}
206 	} else {
207 		isread = USB_GET_DATA_ISREAD(xfer);
208 	}
209 	return (isread);
210 }
211 
212 static uint32_t
213 usbpf_xfer_precompute_size(struct usb_xfer *xfer, int type)
214 {
215 	uint32_t totlen;
216 	uint32_t x;
217 	uint32_t nframes;
218 
219 	if (type == USBPF_XFERTAP_SUBMIT)
220 		nframes = xfer->nframes;
221 	else
222 		nframes = xfer->aframes;
223 
224 	totlen = USBPF_HDR_LEN + (USBPF_FRAME_HDR_LEN * nframes);
225 
226 	/* precompute all trace lengths */
227 	for (x = 0; x != nframes; x++) {
228 		if (usbpf_xfer_frame_is_read(xfer, x)) {
229 			if (type != USBPF_XFERTAP_SUBMIT) {
230 				totlen += USBPF_FRAME_ALIGN(
231 				    xfer->frlengths[x]);
232 			}
233 		} else {
234 			if (type == USBPF_XFERTAP_SUBMIT) {
235 				totlen += USBPF_FRAME_ALIGN(
236 				    xfer->frlengths[x]);
237 			}
238 		}
239 	}
240 	return (totlen);
241 }
242 
243 void
244 usbpf_xfertap(struct usb_xfer *xfer, int type)
245 {
246 	struct usb_bus *bus;
247 	struct usbpf_pkthdr *up;
248 	struct usbpf_framehdr *uf;
249 	usb_frlength_t offset;
250 	uint32_t totlen;
251 	uint32_t frame;
252 	uint32_t temp;
253 	uint32_t nframes;
254 	uint32_t x;
255 	uint8_t *buf;
256 	uint8_t *ptr;
257 
258 	bus = xfer->xroot->bus;
259 
260 	/* sanity checks */
261 	if (usb_no_pf != 0)
262 		return;
263 	if (bus->ifp == NULL)
264 		return;
265 	if (!bpf_peers_present(bus->ifp->if_bpf))
266 		return;
267 
268 	totlen = usbpf_xfer_precompute_size(xfer, type);
269 
270 	if (type == USBPF_XFERTAP_SUBMIT)
271 		nframes = xfer->nframes;
272 	else
273 		nframes = xfer->aframes;
274 
275 	/*
276 	 * XXX TODO XXX
277 	 *
278 	 * When BPF supports it we could pass a fragmented array of
279 	 * buffers avoiding the data copy operation here.
280 	 */
281 	buf = ptr = malloc(totlen, M_TEMP, M_WAITOK);
282 	if (buf == NULL) {
283 		device_printf(bus->parent, "usbpf: Out of memory\n");
284 		return;
285 	}
286 
287 	up = (struct usbpf_pkthdr *)ptr;
288 	ptr += USBPF_HDR_LEN;
289 
290 	/* fill out header */
291 	temp = device_get_unit(bus->bdev);
292 	up->up_totlen = htole32(totlen);
293 	up->up_busunit = htole32(temp);
294 	up->up_address = xfer->xroot->udev->device_index;
295 	if (xfer->flags_int.usb_mode == USB_MODE_DEVICE)
296 		up->up_mode = USBPF_MODE_DEVICE;
297 	else
298 		up->up_mode = USBPF_MODE_HOST;
299 	up->up_type = type;
300 	up->up_xfertype = xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE;
301 	temp = usbpf_aggregate_xferflags(&xfer->flags);
302 	up->up_flags = htole32(temp);
303 	temp = usbpf_aggregate_status(&xfer->flags_int);
304 	up->up_status = htole32(temp);
305 	temp = xfer->error;
306 	up->up_error = htole32(temp);
307 	temp = xfer->interval;
308 	up->up_interval = htole32(temp);
309 	up->up_frames = htole32(nframes);
310 	temp = xfer->max_packet_size;
311 	up->up_packet_size = htole32(temp);
312 	temp = xfer->max_packet_count;
313 	up->up_packet_count = htole32(temp);
314 	temp = xfer->endpointno;
315 	up->up_endpoint = htole32(temp);
316 	up->up_speed = xfer->xroot->udev->speed;
317 
318 	/* clear reserved area */
319 	memset(up->up_reserved, 0, sizeof(up->up_reserved));
320 
321 	/* init offset and frame */
322 	offset = 0;
323 	frame = 0;
324 
325 	/* iterate all the USB frames and copy data, if any */
326 	for (x = 0; x != nframes; x++) {
327 		uint32_t length;
328 		int isread;
329 
330 		/* get length */
331 		length = xfer->frlengths[x];
332 
333 		/* get frame header pointer */
334 		uf = (struct usbpf_framehdr *)ptr;
335 		ptr += USBPF_FRAME_HDR_LEN;
336 
337 		/* fill out packet header */
338 		uf->length = htole32(length);
339 		uf->flags = 0;
340 
341 		/* get information about data read/write */
342 		isread = usbpf_xfer_frame_is_read(xfer, x);
343 
344 		/* check if we need to copy any data */
345 		if (isread) {
346 			if (type == USBPF_XFERTAP_SUBMIT)
347 				length = 0;
348 			else {
349 				uf->flags |= htole32(
350 				    USBPF_FRAMEFLAG_DATA_FOLLOWS);
351 			}
352 		} else {
353 			if (type != USBPF_XFERTAP_SUBMIT)
354 				length = 0;
355 			else {
356 				uf->flags |= htole32(
357 				    USBPF_FRAMEFLAG_DATA_FOLLOWS);
358 			}
359 		}
360 
361 		/* check if data is read direction */
362 		if (isread)
363 			uf->flags |= htole32(USBPF_FRAMEFLAG_READ);
364 
365 		/* copy USB data, if any */
366 		if (length != 0) {
367 			/* copy data */
368 			usbd_copy_out(&xfer->frbuffers[frame],
369 			    offset, ptr, length);
370 
371 			/* align length */
372 			temp = USBPF_FRAME_ALIGN(length);
373 
374 			/* zero pad */
375 			if (temp != length)
376 				memset(ptr + length, 0, temp - length);
377 
378 			ptr += temp;
379 		}
380 
381 		if (xfer->flags_int.isochronous_xfr) {
382 			offset += usbd_xfer_old_frame_length(xfer, x);
383 		} else {
384 			frame ++;
385 		}
386 	}
387 
388 	bpf_tap(bus->ifp->if_bpf, buf, totlen);
389 
390 	free(buf, M_TEMP);
391 }
392