1 /*	$OpenBSD: if_ubt.c,v 1.2 2005/06/24 20:06:11 martin Exp $	*/
2 
3 /*
4  * ng_ubt.c
5  *
6  * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $Id: if_ubt.c,v 1.2 2005/06/24 20:06:11 martin Exp $
31  * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c,v 1.20 2004/10/12 23:33:46 emax Exp $
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/conf.h>
37 #include <sys/device.h>
38 #include <sys/endian.h>
39 #include <sys/fcntl.h>
40 #include <sys/filio.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/poll.h>
45 #include <sys/uio.h>
46 #include <sys/socket.h>
47 
48 #include <machine/bus.h>
49 
50 #include <net/if.h>
51 #include <net/if_types.h>
52 
53 #include <netbt/bluetooth.h>
54 #include <netbt/hci.h>
55 #include <netbt/l2cap.h>
56 #include <netbt/bt.h>
57 #include <netbt/hci_var.h>
58 
59 #include <dev/usb/usb.h>
60 #include <dev/usb/usbdi.h>
61 #include <dev/usb/usbdi_util.h>
62 #include <dev/usb/usbdivar.h>
63 #include <dev/usb/usbdevs.h>
64 
65 #include <dev/usb/if_ubtreg.h>
66 
67 USB_DECLARE_DRIVER(ubt);
68 
69 Static usbd_status	ubt_request_start(struct ubt_softc *);
70 Static void		ubt_request_complete(usbd_xfer_handle,
71 			    usbd_private_handle, usbd_status);
72 
73 Static usbd_status	ubt_intr_start(struct ubt_softc *);
74 Static void		ubt_intr_complete(usbd_xfer_handle,
75 			    usbd_private_handle, usbd_status);
76 
77 Static usbd_status	ubt_bulk_in_start(struct ubt_softc *);
78 Static void		ubt_bulk_in_complete(usbd_xfer_handle,
79 			    usbd_private_handle, usbd_status);
80 
81 Static usbd_status	ubt_bulk_out_start(struct ubt_softc *);
82 Static void		ubt_bulk_out_complete(usbd_xfer_handle,
83 			    usbd_private_handle, usbd_status);
84 
85 Static usbd_status	ubt_isoc_in_start(struct ubt_softc *);
86 Static void		ubt_isoc_in_complete(usbd_xfer_handle,
87 			    usbd_private_handle, usbd_status);
88 
89 Static usbd_status	ubt_isoc_out_start(struct ubt_softc *);
90 Static void		ubt_isoc_out_complete(usbd_xfer_handle,
91 			    usbd_private_handle, usbd_status);
92 
93 Static void		ubt_reset(struct ubt_softc *);
94 Static void		ubt_stop(struct ubt_softc *);
95 
96 Static int		ubt_rcvdata(struct ubt_softc *, struct mbuf *);
97 
98 Static void		ubt_if_start(struct ifnet *);
99 Static int		ubt_if_ioctl(struct ifnet *, u_long, caddr_t);
100 Static int		ubt_if_init(struct ifnet *);
101 Static void		ubt_if_watchdog(struct ifnet *);
102 
USB_MATCH(ubt)103 USB_MATCH(ubt)
104 {
105 	/*
106 	 * If for some reason device should not be attached then put
107 	 * VendorID/ProductID pair into the list below. Currently I
108 	 * do not know of any such devices. The format is as follows:
109 	 *
110 	 *	{ VENDOR_ID, PRODUCT_ID },
111 	 *
112 	 * where VENDOR_ID and PRODUCT_ID are hex numbers.
113 	 */
114 
115 	Static struct usb_devno const	ubt_ignored_devices[] = {
116 		{ 0, 0 } /* This should be the last item in the list */
117 	};
118 
119 	/*
120 	 * If device violates Bluetooth specification and has bDeviceClass,
121 	 * bDeviceSubClass and bDeviceProtocol set to wrong values then you
122 	 * could try to put VendorID/ProductID pair into the list below.
123 	 */
124 
125 	Static struct usb_devno const	ubt_broken_devices[] = {
126 		{ USB_VENDOR_CSR, USB_PRODUCT_CSR_BLUECORE },
127 		{ USB_VENDOR_MSI, USB_PRODUCT_MSI_BLUETOOTH },
128 		{ 0, 0 } /* This should be the last item in the list */
129 	};
130 
131 	USB_MATCH_START(ubt, uaa);
132 
133 	usb_device_descriptor_t	*dd = usbd_get_device_descriptor(uaa->device);
134 
135 	if (uaa->iface == NULL ||
136 	    usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
137 		return (UMATCH_NONE);
138 
139 	if (dd->bDeviceClass == UDCLASS_WIRELESS &&
140 	    dd->bDeviceSubClass == UDSUBCLASS_RF &&
141 	    dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
142 		return (UMATCH_DEVCLASS_DEVSUBCLASS);
143 
144 	if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
145 		return (UMATCH_VENDOR_PRODUCT);
146 
147 	return (UMATCH_NONE);
148 }
149 
USB_ATTACH(ubt)150 USB_ATTACH(ubt)
151 {
152 	USB_ATTACH_START(ubt, sc, uaa);
153 	usb_config_descriptor_t		*cd = NULL;
154 	usb_interface_descriptor_t	*id = NULL;
155 	usb_endpoint_descriptor_t	*ed = NULL;
156 	char				 devinfo[1024];
157 	usbd_status			 error;
158 	int				 i, ai, alt_no, isoc_in, isoc_out,
159 					 isoc_isize, isoc_osize;
160 	struct ifnet *ifp = &sc->sc_if;
161 
162 	/* Get USB device info */
163 	sc->sc_udev = uaa->device;
164 	usbd_devinfo(sc->sc_udev, 0, devinfo, sizeof(devinfo));
165 	USB_ATTACH_SETUP;
166 	printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
167 
168 	/*
169 	 * Initialize device softc structure
170 	 */
171 
172 	/* State */
173 	sc->sc_debug = NG_UBT_WARN_LEVEL;
174 	sc->sc_flags = 0;
175 	NG_UBT_STAT_RESET(sc->sc_stat);
176 
177 	/* Interfaces */
178 	sc->sc_iface0 = sc->sc_iface1 = NULL;
179 
180 	/* Interrupt pipe */
181 	sc->sc_intr_ep = -1;
182 	sc->sc_intr_pipe = NULL;
183 	sc->sc_intr_xfer = NULL;
184 	sc->sc_intr_buffer = NULL;
185 
186 	/* Control pipe */
187 	sc->sc_ctrl_xfer = NULL;
188 	sc->sc_ctrl_buffer = NULL;
189 	NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
190 
191 	/* Bulk-in pipe */
192 	sc->sc_bulk_in_ep = -1;
193 	sc->sc_bulk_in_pipe = NULL;
194 	sc->sc_bulk_in_xfer = NULL;
195 	sc->sc_bulk_in_buffer = NULL;
196 
197 	/* Bulk-out pipe */
198 	sc->sc_bulk_out_ep = -1;
199 	sc->sc_bulk_out_pipe = NULL;
200 	sc->sc_bulk_out_xfer = NULL;
201 	sc->sc_bulk_out_buffer = NULL;
202 	NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
203 
204 	/* Isoc-in pipe */
205 	sc->sc_isoc_in_ep = -1;
206 	sc->sc_isoc_in_pipe = NULL;
207 	sc->sc_isoc_in_xfer = NULL;
208 
209 	/* Isoc-out pipe */
210 	sc->sc_isoc_out_ep = -1;
211 	sc->sc_isoc_out_pipe = NULL;
212 	sc->sc_isoc_out_xfer = NULL;
213 	sc->sc_isoc_size = -1;
214 	NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
215 
216 	/*
217 	 * XXX set configuration?
218 	 *
219 	 * Configure Bluetooth USB device. Discover all required USB interfaces
220 	 * and endpoints.
221 	 *
222 	 * USB device must present two interfaces:
223 	 * 1) Interface 0 that has 3 endpoints
224 	 *	1) Interrupt endpoint to receive HCI events
225 	 *	2) Bulk IN endpoint to receive ACL data
226 	 *	3) Bulk OUT endpoint to send ACL data
227 	 *
228 	 * 2) Interface 1 then has 2 endpoints
229 	 *	1) Isochronous IN endpoint to receive SCO data
230  	 *	2) Isochronous OUT endpoint to send SCO data
231 	 *
232 	 * Interface 1 (with isochronous endpoints) has several alternate
233 	 * configurations with different packet size.
234 	 */
235 
236 	/*
237 	 * Interface 0
238 	 */
239 
240 	error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
241 	if (error || sc->sc_iface0 == NULL) {
242 		printf("%s: Could not get interface 0 handle. %s (%d), " \
243 			"handle=%p\n", USBDEVNAME(sc->sc_dev),
244 			usbd_errstr(error), error, sc->sc_iface0);
245 		goto bad;
246 	}
247 
248 	id = usbd_get_interface_descriptor(sc->sc_iface0);
249 	if (id == NULL) {
250 		printf("%s: Could not get interface 0 descriptor\n",
251 			USBDEVNAME(sc->sc_dev));
252 		goto bad;
253 	}
254 
255 	for (i = 0; i < id->bNumEndpoints; i ++) {
256 		ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
257 		if (ed == NULL) {
258 			printf("%s: Could not read endpoint descriptor for " \
259 				"interface 0, i=%d\n", USBDEVNAME(sc->sc_dev),
260 				i);
261 			goto bad;
262 		}
263 
264 		switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
265 		case UE_BULK:
266 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
267 				sc->sc_bulk_in_ep = ed->bEndpointAddress;
268 			else
269 				sc->sc_bulk_out_ep = ed->bEndpointAddress;
270 			break;
271 
272 		case UE_INTERRUPT:
273 			sc->sc_intr_ep = ed->bEndpointAddress;
274 			break;
275 		}
276 	}
277 
278 	/* Check if we got everything we wanted on Interface 0 */
279 	if (sc->sc_intr_ep == -1) {
280 		printf("%s: Could not detect interrupt endpoint\n",
281 			USBDEVNAME(sc->sc_dev));
282 		goto bad;
283 	}
284 	if (sc->sc_bulk_in_ep == -1) {
285 		printf("%s: Could not detect bulk-in endpoint\n",
286 			USBDEVNAME(sc->sc_dev));
287 		goto bad;
288 	}
289 	if (sc->sc_bulk_out_ep == -1) {
290 		printf("%s: Could not detect bulk-out endpoint\n",
291 			USBDEVNAME(sc->sc_dev));
292 		goto bad;
293 	}
294 
295 	printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
296 		"bulk-out=%#x\n", USBDEVNAME(sc->sc_dev),
297 		sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
298 
299 	/*
300 	 * Interface 1
301 	 */
302 
303 	cd = usbd_get_config_descriptor(sc->sc_udev);
304 	if (cd == NULL) {
305 		printf("%s: Could not get device configuration descriptor\n",
306 			USBDEVNAME(sc->sc_dev));
307 		goto bad;
308 	}
309 
310 	error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
311 	if (error || sc->sc_iface1 == NULL) {
312 		printf("%s: Could not get interface 1 handle. %s (%d), " \
313 			"handle=%p\n", USBDEVNAME(sc->sc_dev),
314 			usbd_errstr(error), error, sc->sc_iface1);
315 		goto bad;
316 	}
317 
318 	id = usbd_get_interface_descriptor(sc->sc_iface1);
319 	if (id == NULL) {
320 		printf("%s: Could not get interface 1 descriptor\n",
321 			USBDEVNAME(sc->sc_dev));
322 		goto bad;
323 	}
324 
325 	/*
326 	 * Scan all alternate configurations for interface 1
327 	 */
328 
329 	alt_no = -1;
330 
331 	for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++)  {
332 		error = usbd_set_interface(sc->sc_iface1, ai);
333 		if (error) {
334 			printf("%s: [SCAN] Could not set alternate " \
335 				"configuration %d for interface 1. %s (%d)\n",
336 				USBDEVNAME(sc->sc_dev),  ai, usbd_errstr(error),
337 				error);
338 			goto bad;
339 		}
340 		id = usbd_get_interface_descriptor(sc->sc_iface1);
341 		if (id == NULL) {
342 			printf("%s: Could not get interface 1 descriptor for " \
343 				"alternate configuration %d\n",
344 				USBDEVNAME(sc->sc_dev), ai);
345 			goto bad;
346 		}
347 
348 		isoc_in = isoc_out = -1;
349 		isoc_isize = isoc_osize = 0;
350 
351 		for (i = 0; i < id->bNumEndpoints; i ++) {
352 			ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
353 			if (ed == NULL) {
354 				printf("%s: Could not read endpoint " \
355 					"descriptor for interface 1, " \
356 					"alternate configuration %d, i=%d\n",
357 					USBDEVNAME(sc->sc_dev), ai, i);
358 				goto bad;
359 			}
360 
361 			if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
362 				continue;
363 
364 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
365 				isoc_in = ed->bEndpointAddress;
366 				isoc_isize = UGETW(ed->wMaxPacketSize);
367 			} else {
368 				isoc_out = ed->bEndpointAddress;
369 				isoc_osize = UGETW(ed->wMaxPacketSize);
370 			}
371 		}
372 
373 		/*
374 		 * Make sure that configuration looks sane and if so
375 		 * update current settings
376 		 */
377 
378 		if (isoc_in != -1 && isoc_out != -1 &&
379 		    isoc_isize > 0  && isoc_osize > 0 &&
380 		    isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
381 			sc->sc_isoc_in_ep = isoc_in;
382 			sc->sc_isoc_out_ep = isoc_out;
383 			sc->sc_isoc_size = isoc_isize;
384 			alt_no = ai;
385 		}
386 	}
387 
388 	/* Check if we got everything we wanted on Interface 0 */
389 	if (sc->sc_isoc_in_ep == -1) {
390 		printf("%s: Could not detect isoc-in endpoint\n",
391 			USBDEVNAME(sc->sc_dev));
392 		goto bad;
393 	}
394 	if (sc->sc_isoc_out_ep == -1) {
395 		printf("%s: Could not detect isoc-out endpoint\n",
396 			USBDEVNAME(sc->sc_dev));
397 		goto bad;
398 	}
399 	if (sc->sc_isoc_size <= 0) {
400 		printf("%s: Invalid isoc. packet size=%d\n",
401 			USBDEVNAME(sc->sc_dev), sc->sc_isoc_size);
402 		goto bad;
403 	}
404 
405 	error = usbd_set_interface(sc->sc_iface1, alt_no);
406 	if (error) {
407 		printf("%s: Could not set alternate configuration " \
408 			"%d for interface 1. %s (%d)\n", USBDEVNAME(sc->sc_dev),
409 			alt_no, usbd_errstr(error), error);
410 		goto bad;
411 	}
412 
413 	/* Allocate USB transfer handles and buffers */
414 	sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
415 	if (sc->sc_ctrl_xfer == NULL) {
416 		printf("%s: Could not allocate control xfer handle\n",
417 			USBDEVNAME(sc->sc_dev));
418 		goto bad;
419 	}
420 	sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
421 						UBT_CTRL_BUFFER_SIZE);
422 	if (sc->sc_ctrl_buffer == NULL) {
423 		printf("%s: Could not allocate control buffer\n",
424 			USBDEVNAME(sc->sc_dev));
425 		goto bad;
426 	}
427 
428 	sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
429 	if (sc->sc_intr_xfer == NULL) {
430 		printf("%s: Could not allocate interrupt xfer handle\n",
431 			USBDEVNAME(sc->sc_dev));
432 		goto bad;
433 	}
434 	sc->sc_intr_buffer = usbd_alloc_buffer(sc->sc_intr_xfer,
435 						UBT_INTR_BUFFER_SIZE);
436 	if (sc->sc_intr_buffer == NULL) {
437 		printf("%s: Could not allocate interrupt buffer\n",
438 			USBDEVNAME(sc->sc_dev));
439 		goto bad;
440 	}
441 
442 	sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
443 	if (sc->sc_bulk_in_xfer == NULL) {
444 		printf("%s: Could not allocate bulk-in xfer handle\n",
445 			USBDEVNAME(sc->sc_dev));
446 		goto bad;
447 	}
448 	sc->sc_bulk_in_buffer = usbd_alloc_buffer(sc->sc_bulk_in_xfer,
449 						UBT_BULK_BUFFER_SIZE);
450 	if (sc->sc_bulk_in_buffer == NULL) {
451 		printf("%s: Could not allocate bulk-in buffer\n",
452 			USBDEVNAME(sc->sc_dev));
453 		goto bad;
454 	}
455 
456 	sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
457 	if (sc->sc_bulk_out_xfer == NULL) {
458 		printf("%s: Could not allocate bulk-out xfer handle\n",
459 			USBDEVNAME(sc->sc_dev));
460 		goto bad;
461 	}
462 	sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
463 						UBT_BULK_BUFFER_SIZE);
464 	if (sc->sc_bulk_out_buffer == NULL) {
465 		printf("%s: Could not allocate bulk-out buffer\n",
466 			USBDEVNAME(sc->sc_dev));
467 		goto bad;
468 	}
469 
470 	/*
471 	 * Allocate buffers for isoc. transfers
472 	 */
473 
474 	sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
475 
476 	sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
477 	if (sc->sc_isoc_in_xfer == NULL) {
478 		printf("%s: Could not allocate isoc-in xfer handle\n",
479 			USBDEVNAME(sc->sc_dev));
480 		goto bad;
481 	}
482 	sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
483 					sc->sc_isoc_nframes * sc->sc_isoc_size);
484 	if (sc->sc_isoc_in_buffer == NULL) {
485 		printf("%s: Could not allocate isoc-in buffer\n",
486 			USBDEVNAME(sc->sc_dev));
487 		goto bad;
488 	}
489 	sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
490 						M_USBDEV, M_NOWAIT);
491 	if (sc->sc_isoc_in_frlen == NULL) {
492 		printf("%s: Could not allocate isoc-in frame sizes buffer\n",
493 			USBDEVNAME(sc->sc_dev));
494 		goto bad;
495 	}
496 
497 	sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
498 	if (sc->sc_isoc_out_xfer == NULL) {
499 		printf("%s: Could not allocate isoc-out xfer handle\n",
500 			USBDEVNAME(sc->sc_dev));
501 		goto bad;
502 	}
503 	sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
504 					sc->sc_isoc_nframes * sc->sc_isoc_size);
505 	if (sc->sc_isoc_out_buffer == NULL) {
506 		printf("%s: Could not allocate isoc-out buffer\n",
507 			USBDEVNAME(sc->sc_dev));
508 		goto bad;
509 	}
510 	sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
511 						M_USBDEV, M_NOWAIT);
512 	if (sc->sc_isoc_out_frlen == NULL) {
513 		printf("%s: Could not allocate isoc-out frame sizes buffer\n",
514 			USBDEVNAME(sc->sc_dev));
515 		goto bad;
516 	}
517 
518 	printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
519 		"isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
520 		USBDEVNAME(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
521 		sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes,
522 		(sc->sc_isoc_nframes * sc->sc_isoc_size));
523 
524 	/*
525 	 * Open pipes
526 	 */
527 
528 	/* Interrupt */
529 	error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
530 			USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
531 	if (error != USBD_NORMAL_COMPLETION) {
532 		printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
533 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
534 			error);
535 		goto bad;
536 	}
537 
538 	/* Bulk-in */
539 	error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
540 			USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
541 	if (error != USBD_NORMAL_COMPLETION) {
542 		printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
543 			__func__,  USBDEVNAME(sc->sc_dev), usbd_errstr(error),
544 			error);
545 		goto bad;
546 	}
547 
548 	/* Bulk-out */
549 	error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
550 			USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
551 	if (error != USBD_NORMAL_COMPLETION) {
552 		printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
553 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
554 			error);
555 		goto bad;
556 	}
557 
558 #if __broken__ /* XXX FIXME */
559 	/* Isoc-in */
560 	error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
561 			USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
562 	if (error != USBD_NORMAL_COMPLETION) {
563 		printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
564 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
565 			error);
566 		goto bad;
567 	}
568 
569 	/* Isoc-out */
570 	error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
571 			USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
572 	if (error != USBD_NORMAL_COMPLETION) {
573 		printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
574 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
575 			error);
576 		goto bad;
577 	}
578 #endif /* __broken__ */
579 
580 	/* Start intr transfer */
581 	error = ubt_intr_start(sc);
582 	if (error != USBD_NORMAL_COMPLETION) {
583 		NG_UBT_ALERT(
584 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
585 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
586 			error);
587 		goto bad;
588 	}
589 
590 	/* Start bulk-in transfer */
591 	error = ubt_bulk_in_start(sc);
592 	if (error != USBD_NORMAL_COMPLETION) {
593 		NG_UBT_ALERT(
594 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
595 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
596 			error);
597 		goto bad;
598 	}
599 
600 #if __broken__ /* XXX FIXME */
601 	/* Start isoc-in transfer */
602 	error = ubt_isoc_in_start(sc);
603 	if (error != USBD_NORMAL_COMPLETION) {
604 		NG_UBT_ALERT(
605 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
606 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
607 			error);
608 		goto bad;
609 	}
610 #endif /* __broken__ */
611 
612 	/* Claim all interfaces on the device */
613 	for (i = 0; i < uaa->nifaces; i++)
614 		uaa->ifaces[i] = NULL;
615 
616 	/* Attach network interface */
617 	bzero(ifp, sizeof(*ifp));
618 	strlcpy(ifp->if_xname, USBDEVNAME(sc->sc_dev), sizeof(ifp->if_xname));
619 	ifp->if_softc = sc;
620 	ifp->if_mtu = 65536;
621 	ifp->if_start = ubt_if_start;
622 	ifp->if_ioctl = ubt_if_ioctl;
623 	ifp->if_init = ubt_if_init;
624 	ifp->if_watchdog = ubt_if_watchdog;
625 	ifp->if_type = IFT_BLUETOOTH;
626 	IFQ_SET_READY(&ifp->if_snd);
627 	if_attach(ifp);
628 	if_alloc_sadl(ifp);
629 
630 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
631 		USBDEV(sc->sc_dev));
632 
633 	USB_ATTACH_SUCCESS_RETURN;
634 bad:
635 #if 0
636 	ubt_detach(self);
637 #endif
638 	USB_ATTACH_ERROR_RETURN;
639 }
640 
USB_DETACH(ubt)641 USB_DETACH(ubt)
642 {
643 	USB_DETACH_START(ubt, sc);
644 	struct ifnet *ifp = &sc->sc_if;
645 
646 	/* Close pipes */
647 	if (sc->sc_intr_pipe != NULL) {
648 		usbd_close_pipe(sc->sc_intr_pipe);
649 		sc->sc_intr_pipe = NULL;
650 	}
651 
652 	if (sc->sc_bulk_in_pipe != NULL) {
653 		usbd_close_pipe(sc->sc_bulk_in_pipe);
654 		sc->sc_bulk_in_pipe = NULL;
655 	}
656 	if (sc->sc_bulk_out_pipe != NULL) {
657 		usbd_close_pipe(sc->sc_bulk_out_pipe);
658 		sc->sc_bulk_out_pipe = NULL;
659 	}
660 
661 	if (sc->sc_isoc_in_pipe != NULL) {
662 		usbd_close_pipe(sc->sc_isoc_in_pipe);
663 		sc->sc_isoc_in_pipe = NULL;
664 	}
665 	if (sc->sc_isoc_out_pipe != NULL) {
666 		usbd_close_pipe(sc->sc_isoc_out_pipe);
667 		sc->sc_isoc_out_pipe = NULL;
668 	}
669 
670 	/* Destroy USB transfer handles */
671 	if (sc->sc_ctrl_xfer != NULL) {
672 		usbd_free_xfer(sc->sc_ctrl_xfer);
673 		sc->sc_ctrl_xfer = NULL;
674 	}
675 
676 	if (sc->sc_intr_xfer != NULL) {
677 		usbd_free_xfer(sc->sc_intr_xfer);
678 		sc->sc_intr_xfer = NULL;
679 	}
680 
681 	if (sc->sc_bulk_in_xfer != NULL) {
682 		usbd_free_xfer(sc->sc_bulk_in_xfer);
683 		sc->sc_bulk_in_xfer = NULL;
684 	}
685 	if (sc->sc_bulk_out_xfer != NULL) {
686 		usbd_free_xfer(sc->sc_bulk_out_xfer);
687 		sc->sc_bulk_out_xfer = NULL;
688 	}
689 
690 	if (sc->sc_isoc_in_xfer != NULL) {
691 		usbd_free_xfer(sc->sc_isoc_in_xfer);
692 		sc->sc_isoc_in_xfer = NULL;
693 	}
694 	if (sc->sc_isoc_out_xfer != NULL) {
695 		usbd_free_xfer(sc->sc_isoc_out_xfer);
696 		sc->sc_isoc_out_xfer = NULL;
697 	}
698 
699 	/* Destroy isoc. frame size buffers */
700 	if (sc->sc_isoc_in_frlen != NULL) {
701 		free(sc->sc_isoc_in_frlen, M_USBDEV);
702 		sc->sc_isoc_in_frlen = NULL;
703 	}
704 	if (sc->sc_isoc_out_frlen != NULL) {
705 		free(sc->sc_isoc_out_frlen, M_USBDEV);
706 		sc->sc_isoc_out_frlen = NULL;
707 	}
708 
709 #if 0
710 	/* Destroy queues */
711 	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
712 	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
713 	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
714 #endif
715 
716 	if_detach(ifp);
717 
718 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
719 			USBDEV(sc->sc_dev));
720 
721 	return (0);
722 }
723 
724 int
ubt_activate(device_ptr_t self,enum devact act)725 ubt_activate(device_ptr_t self, enum devact act)
726 {
727 	switch (act) {
728 	case DVACT_ACTIVATE:
729 		return (EOPNOTSUPP);
730 	case DVACT_DEACTIVATE:
731 		break;
732 	}
733 
734 	return (0);
735 }
736 
737 /*
738  * Start USB control request (HCI command).
739  */
740 Static usbd_status
ubt_request_start(struct ubt_softc * sc)741 ubt_request_start(struct ubt_softc * sc)
742 {
743 	usb_device_request_t	 req;
744 	struct mbuf		*m = NULL;
745 	usbd_status		 status;
746 
747 	KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
748 "%s: %s - Another control request is pending\n",
749 		__func__, USBDEVNAME(sc->sc_dev)));
750 
751 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
752 	if (m == NULL) {
753 		NG_UBT_INFO(
754 "%s: %s - HCI command queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
755 
756 		return (USBD_NORMAL_COMPLETION);
757 	}
758 
759 	/*
760 	 * Check HCI command frame size and copy it back to
761 	 * linear USB transfer buffer.
762 	 */
763 
764 	if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
765 		panic("%s: %s - HCI command frame too big, size=%lu, len=%d\n",
766 			__func__, USBDEVNAME(sc->sc_dev), (u_long)UBT_CTRL_BUFFER_SIZE,
767 			m->m_pkthdr.len);
768 
769 	m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
770 
771 	/* Initialize a USB control request and then schedule it */
772 	bzero(&req, sizeof(req));
773 	req.bmRequestType = UBT_HCI_REQUEST;
774 	USETW(req.wLength, m->m_pkthdr.len);
775 
776 	NG_UBT_INFO(
777 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
778 		__func__, USBDEVNAME(sc->sc_dev), req.bmRequestType,
779 		UGETW(req.wLength));
780 
781 	usbd_setup_default_xfer(
782 		sc->sc_ctrl_xfer,
783 		sc->sc_udev,
784 		(usbd_private_handle) sc,
785 		USBD_DEFAULT_TIMEOUT, /* XXX */
786 		&req,
787 		sc->sc_ctrl_buffer,
788 		m->m_pkthdr.len,
789 		USBD_NO_COPY,
790 		ubt_request_complete);
791 
792 	status = usbd_transfer(sc->sc_ctrl_xfer);
793 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
794 		NG_UBT_ERR(
795 "%s: %s - Could not start control request. %s (%d)\n",
796 			__func__, USBDEVNAME(sc->sc_dev),
797 			usbd_errstr(status), status);
798 
799 		NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
800 		NG_UBT_STAT_OERROR(sc->sc_stat);
801 
802 		/* XXX FIXME should we try to resubmit another request? */
803 	} else {
804 		NG_UBT_INFO(
805 "%s: %s - Control request has been started\n",
806 			__func__, USBDEVNAME(sc->sc_dev));
807 
808 		sc->sc_flags |= UBT_CMD_XMIT;
809 		status = USBD_NORMAL_COMPLETION;
810 	}
811 
812 	NG_FREE_M(m);
813 
814 	return (status);
815 } /* ubt_request_start */
816 
817 /*
818  * USB control request callback
819  */
820 Static void
ubt_request_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)821 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
822 {
823 	struct ubt_softc *		sc = p;
824 
825 	if (sc == NULL)
826 		return;
827 
828 	KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
829 "%s: %s - No control request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
830 
831 	sc->sc_flags &= ~UBT_CMD_XMIT;
832 
833 	if (s == USBD_CANCELLED) {
834 		NG_UBT_INFO(
835 "%s: %s - Control request cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
836 
837 		return;
838 	}
839 
840 	if (s != USBD_NORMAL_COMPLETION) {
841 		NG_UBT_ERR(
842 "%s: %s - Control request failed. %s (%d)\n",
843 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
844 
845 		if (s == USBD_STALLED)
846 			usbd_clear_endpoint_stall_async(h->pipe);
847 
848 		NG_UBT_STAT_OERROR(sc->sc_stat);
849 	} else {
850 		NG_UBT_INFO(
851 "%s: %s - Sent %d bytes to control pipe\n",
852 			__func__, USBDEVNAME(sc->sc_dev), h->actlen);
853 
854 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
855 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
856 	}
857 
858 	if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
859 		ubt_request_start(sc);
860 } /* ubt_request_complete2 */
861 
862 /*
863  * Start interrupt transfer. Must be called when node is locked
864  */
865 
866 Static usbd_status
ubt_intr_start(struct ubt_softc * sc)867 ubt_intr_start(struct ubt_softc * sc)
868 {
869 	struct mbuf	*m = NULL;
870 	usbd_status	 status;
871 
872 	KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
873 "%s: %s - Another interrupt request is pending\n",
874 		__func__, USBDEVNAME(sc->sc_dev)));
875 
876 	/* Allocate new mbuf cluster */
877 	MGETHDR(m, M_DONTWAIT, MT_DATA);
878 	if (m == NULL)
879 		return (USBD_NOMEM);
880 
881 	MCLGET(m, M_DONTWAIT);
882 	if (!(m->m_flags & M_EXT)) {
883 		NG_FREE_M(m);
884 		return (USBD_NOMEM);
885 	}
886 
887 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
888 		*mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
889 		m->m_pkthdr.len = m->m_len = 1;
890 	} else
891 		m->m_pkthdr.len = m->m_len = 0;
892 
893 	/* Initialize a USB transfer and then schedule it */
894 	usbd_setup_xfer(
895 			sc->sc_intr_xfer,
896 			sc->sc_intr_pipe,
897 			(usbd_private_handle) sc,
898 			sc->sc_intr_buffer,
899 			UBT_INTR_BUFFER_SIZE,
900 			USBD_SHORT_XFER_OK,
901 			USBD_NO_TIMEOUT,
902 			ubt_intr_complete);
903 
904 	status = usbd_transfer(sc->sc_intr_xfer);
905 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
906 		NG_UBT_ERR(
907 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
908 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
909 			status);
910 
911 		NG_FREE_M(m);
912 
913 		return (status);
914 	}
915 
916 	sc->sc_flags |= UBT_EVT_RECV;
917 	sc->sc_intr_mbuf = m;
918 
919 	return (USBD_NORMAL_COMPLETION);
920 } /* ubt_intr_start */
921 
922 /*
923  * Process interrupt from USB device (We got data from interrupt pipe)
924  */
925 Static void
ubt_intr_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)926 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
927 {
928 	struct ubt_softc *	sc = p;
929 	struct mbuf		*m = NULL;
930 	ng_hci_event_pkt_t	*hdr = NULL;
931 	int			error = 0;
932 
933 	if (sc == NULL)
934 		return;
935 
936 	KASSERT((sc->sc_flags & UBT_EVT_RECV), (
937 "%s: %s - No interrupt request is pending\n",
938 		__func__, USBDEVNAME(sc->sc_dev)));
939 
940 	sc->sc_flags &= ~UBT_EVT_RECV;
941 
942 	m = sc->sc_intr_mbuf;
943 	bcopy(sc->sc_intr_buffer, mtod(m, void *) + m->m_len, h->actlen);
944 
945 	hdr = mtod(m, ng_hci_event_pkt_t *);
946 
947 	if (s == USBD_CANCELLED) {
948 		NG_UBT_INFO(
949 "%s: %s - Interrupt xfer cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
950 
951 		NG_FREE_M(m);
952 		return;
953 	}
954 
955 	if (s != USBD_NORMAL_COMPLETION) {
956 		NG_UBT_WARN(
957 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
958 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
959 
960 		if (s == USBD_STALLED)
961 			usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
962 
963 		NG_UBT_STAT_IERROR(sc->sc_stat);
964 		NG_FREE_M(m);
965 
966 		return; /* XXX FIXME we should restart after some delay */
967 	}
968 
969 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
970 	m->m_pkthdr.len += h->actlen;
971 	m->m_len += h->actlen;
972 
973 	NG_UBT_INFO(
974 "%s: %s - Got %d bytes from interrupt pipe\n",
975 		__func__, USBDEVNAME(sc->sc_dev), h->actlen);
976 
977 	if (m->m_pkthdr.len < sizeof(*hdr)) {
978 		NG_FREE_M(m);
979 		goto done;
980 	}
981 
982 	if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
983 		NG_UBT_INFO(
984 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
985 			__func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
986 			hdr->length);
987 
988 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
989 
990 #if 0
991 		NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
992 #endif
993 		ng_btsocket_hci_raw_node_rcvdata(&sc->sc_if, m);
994 		if (error != 0)
995 			NG_UBT_STAT_IERROR(sc->sc_stat);
996 	} else {
997 		NG_UBT_ERR(
998 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
999 			__func__, USBDEVNAME(sc->sc_dev), hdr->length,
1000 			m->m_pkthdr.len);
1001 
1002 		NG_UBT_STAT_IERROR(sc->sc_stat);
1003 		NG_FREE_M(m);
1004 	}
1005 done:
1006 	ubt_intr_start(sc);
1007 } /* ubt_intr_complete */
1008 
1009 /*
1010  * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1011  */
1012 Static usbd_status
ubt_bulk_in_start(struct ubt_softc * sc)1013 ubt_bulk_in_start(struct ubt_softc * sc)
1014 {
1015 	struct mbuf	*m = NULL;
1016 	usbd_status	 status;
1017 
1018 	KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1019 "%s: %s - Another bulk-in request is pending\n",
1020 		__func__, USBDEVNAME(sc->sc_dev)));
1021 
1022 	/* Allocate new mbuf cluster */
1023 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1024 	if (m == NULL)
1025 		return (USBD_NOMEM);
1026 
1027 	MCLGET(m, M_DONTWAIT);
1028 	if (!(m->m_flags & M_EXT)) {
1029 		NG_FREE_M(m);
1030 		return (USBD_NOMEM);
1031 	}
1032 
1033 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1034 		*mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1035 		m->m_pkthdr.len = m->m_len = 1;
1036 	} else
1037 		m->m_pkthdr.len = m->m_len = 0;
1038 
1039 	/* Initialize a bulk-in USB transfer and then schedule it */
1040 	usbd_setup_xfer(
1041 			sc->sc_bulk_in_xfer,
1042 			sc->sc_bulk_in_pipe,
1043 			(usbd_private_handle) sc,
1044 			sc->sc_bulk_in_buffer,
1045 			UBT_BULK_BUFFER_SIZE,
1046 			USBD_SHORT_XFER_OK,
1047 			USBD_NO_TIMEOUT,
1048 			ubt_bulk_in_complete);
1049 
1050 	status = usbd_transfer(sc->sc_bulk_in_xfer);
1051 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1052 		NG_UBT_ERR(
1053 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1054 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1055 			status);
1056 
1057 		NG_FREE_M(m);
1058 
1059 		return (status);
1060 	}
1061 
1062 	sc->sc_flags |= UBT_ACL_RECV;
1063 	sc->sc_bulk_in_mbuf = m;
1064 
1065 	return (USBD_NORMAL_COMPLETION);
1066 } /* ubt_bulk_in_start */
1067 
1068 /*
1069  * USB bulk-in transfer callback
1070  */
1071 Static void
ubt_bulk_in_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)1072 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1073 {
1074 	struct ubt_softc *	sc = p;
1075 	struct mbuf		*m = NULL;
1076 	ng_hci_acldata_pkt_t	*hdr = NULL;
1077 	int			 len;
1078 
1079 	if (sc == NULL)
1080 		return;
1081 
1082 	KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1083 "%s: %s - No bulk-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1084 
1085 	sc->sc_flags &= ~UBT_ACL_RECV;
1086 
1087 	m = sc->sc_bulk_in_mbuf;
1088 	bcopy(sc->sc_intr_buffer, mtod(m, void *) + m->m_len, h->actlen);
1089 
1090 	hdr = mtod(m, ng_hci_acldata_pkt_t *);
1091 
1092 	if (s == USBD_CANCELLED) {
1093 		NG_UBT_INFO(
1094 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1095 			__func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_in_pipe);
1096 
1097 		NG_FREE_M(m);
1098 		return;
1099 	}
1100 
1101 	if (s != USBD_NORMAL_COMPLETION) {
1102 		NG_UBT_WARN(
1103 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1104 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1105 
1106 		if (s == USBD_STALLED)
1107 			usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1108 
1109 		NG_UBT_STAT_IERROR(sc->sc_stat);
1110 		NG_FREE_M(m);
1111 
1112 		return; /* XXX FIXME we should restart after some delay */
1113 	}
1114 
1115 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1116 	m->m_pkthdr.len += h->actlen;
1117 	m->m_len += h->actlen;
1118 
1119 	NG_UBT_INFO(
1120 "%s: %s - Got %d bytes from bulk-in pipe\n",
1121 		__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1122 
1123 	if (m->m_pkthdr.len < sizeof(*hdr)) {
1124 		NG_FREE_M(m);
1125 		goto done;
1126 	}
1127 
1128 	len = le16toh(hdr->length);
1129 	if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1130 		NG_UBT_INFO(
1131 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1132 			__func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, len);
1133 
1134 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1135 
1136 #if 0
1137 		NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1138 #endif
1139 		if (len != 0)
1140 			NG_UBT_STAT_IERROR(sc->sc_stat);
1141 	} else {
1142 		NG_UBT_ERR(
1143 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1144 			__func__, USBDEVNAME(sc->sc_dev), len,
1145 			m->m_pkthdr.len);
1146 
1147 		NG_UBT_STAT_IERROR(sc->sc_stat);
1148 		NG_FREE_M(m);
1149 	}
1150 done:
1151 	ubt_bulk_in_start(sc);
1152 } /* ubt_bulk_in_complete2 */
1153 
1154 /*
1155  * Start bulk-out USB transfer. Must be called with node locked
1156  */
1157 
1158 Static usbd_status
ubt_bulk_out_start(struct ubt_softc * sc)1159 ubt_bulk_out_start(struct ubt_softc * sc)
1160 {
1161 	struct mbuf	*m = NULL;
1162 	usbd_status	status;
1163 
1164 	KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1165 "%s: %s - Another bulk-out request is pending\n",
1166 		__func__, USBDEVNAME(sc->sc_dev)));
1167 
1168 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1169 	if (m == NULL) {
1170 		NG_UBT_INFO(
1171 "%s: %s - ACL data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1172 
1173  		return (USBD_NORMAL_COMPLETION);
1174 	}
1175 
1176 	/*
1177 	 * Check ACL data frame size and copy it back to linear USB
1178 	 * transfer buffer.
1179 	 */
1180 
1181 	if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1182 		panic(
1183 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1184 			__func__, USBDEVNAME(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1185 			m->m_pkthdr.len);
1186 
1187 	m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1188 
1189 	/* Initialize a bulk-out USB transfer and then schedule it */
1190 	usbd_setup_xfer(
1191 			sc->sc_bulk_out_xfer,
1192 			sc->sc_bulk_out_pipe,
1193 			(usbd_private_handle) sc,
1194 			sc->sc_bulk_out_buffer,
1195 			m->m_pkthdr.len,
1196 			USBD_NO_COPY,
1197 			USBD_DEFAULT_TIMEOUT, /* XXX */
1198 			ubt_bulk_out_complete);
1199 
1200 	status = usbd_transfer(sc->sc_bulk_out_xfer);
1201 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1202 		NG_UBT_ERR(
1203 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1204 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1205 			status);
1206 
1207 		NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1208 		NG_UBT_STAT_OERROR(sc->sc_stat);
1209 
1210 		/* XXX FIXME should we try to start another transfer? */
1211 	} else {
1212 		NG_UBT_INFO(
1213 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1214 			__func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len);
1215 
1216 		sc->sc_flags |= UBT_ACL_XMIT;
1217 		status = USBD_NORMAL_COMPLETION;
1218 	}
1219 
1220 	NG_FREE_M(m);
1221 
1222 	return (status);
1223 } /* ubt_bulk_out_start */
1224 
1225 /*
1226  * USB bulk-out transfer callback
1227  */
1228 Static void
ubt_bulk_out_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)1229 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1230 {
1231 	struct ubt_softc *	sc = p;
1232 
1233 	if (sc == NULL)
1234 		return;
1235 
1236 	KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1237 "%s: %s - No bulk-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1238 
1239 	sc->sc_flags &= ~UBT_ACL_XMIT;
1240 
1241 	if (s == USBD_CANCELLED) {
1242 		NG_UBT_INFO(
1243 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1244 			__func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_out_pipe);
1245 
1246 		return;
1247 	}
1248 
1249 	if (s != USBD_NORMAL_COMPLETION) {
1250 		NG_UBT_WARN(
1251 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1252 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1253 
1254 		if (s == USBD_STALLED)
1255 			usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1256 
1257 		NG_UBT_STAT_OERROR(sc->sc_stat);
1258 	} else {
1259 		NG_UBT_INFO(
1260 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1261 			__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1262 
1263 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1264 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1265 	}
1266 
1267 	if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1268 		ubt_bulk_out_start(sc);
1269 } /* ubt_bulk_out_complete2 */
1270 
1271 /*
1272  * Start Isochronous-in USB transfer. Must be called with node locked
1273  */
1274 
1275 Static usbd_status
ubt_isoc_in_start(struct ubt_softc * sc)1276 ubt_isoc_in_start(struct ubt_softc * sc)
1277 {
1278 	usbd_status	status;
1279 	int		i;
1280 
1281 	KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1282 "%s: %s - Another isoc-in request is pending\n",
1283                 __func__, USBDEVNAME(sc->sc_dev)));
1284 
1285 	/* Initialize a isoc-in USB transfer and then schedule it */
1286 	for (i = 0; i < sc->sc_isoc_nframes; i++)
1287 		sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1288 
1289 	usbd_setup_isoc_xfer(
1290 			sc->sc_isoc_in_xfer,
1291 			sc->sc_isoc_in_pipe,
1292 			(usbd_private_handle) sc,
1293 			sc->sc_isoc_in_frlen,
1294 			sc->sc_isoc_nframes,
1295 			USBD_NO_COPY, /* XXX flags */
1296 			ubt_isoc_in_complete);
1297 
1298 	status = usbd_transfer(sc->sc_isoc_in_xfer);
1299 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1300 		NG_UBT_ERR(
1301 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1302 			__func__, USBDEVNAME(sc->sc_dev),
1303 			usbd_errstr(status), status);
1304 
1305 		return (status);
1306 	}
1307 
1308 	sc->sc_flags |= UBT_SCO_RECV;
1309 
1310 	return (USBD_NORMAL_COMPLETION);
1311 } /* ubt_isoc_in_start */
1312 
1313 /*
1314  * USB isochronous transfer callback
1315  */
1316 Static void
ubt_isoc_in_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)1317 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1318 {
1319 	struct ubt_softc *	sc = p;
1320 	struct mbuf		*m = NULL;
1321 	ng_hci_scodata_pkt_t	*hdr = NULL;
1322 	u_int8_t		*b = NULL;
1323 	int			 i;
1324 
1325 	if (sc == NULL)
1326 		return;
1327 
1328 	KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1329 "%s: %s - No isoc-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1330 
1331 	sc->sc_flags &= ~UBT_SCO_RECV;
1332 
1333 #if 0
1334 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1335 		NG_UBT_INFO(
1336 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1337 
1338 		return;
1339 	}
1340 #endif
1341 
1342 	if (s == USBD_CANCELLED) {
1343 		NG_UBT_INFO(
1344 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1345 			__func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_in_pipe);
1346 
1347 		return;
1348 	}
1349 
1350 	if (s != USBD_NORMAL_COMPLETION) {
1351 		NG_UBT_WARN(
1352 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1353 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1354 
1355 		if (s == USBD_STALLED)
1356 			usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1357 
1358 		NG_UBT_STAT_IERROR(sc->sc_stat);
1359 
1360 		return; /* XXX FIXME we should restart after some delay */
1361 	}
1362 
1363 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1364 
1365 	NG_UBT_INFO(
1366 "%s: %s - Got %d bytes from isoc-in pipe\n",
1367 		__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1368 
1369 	/* Copy SCO data frame to mbuf */
1370 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1371 	if (m == NULL) {
1372 		NG_UBT_ALERT(
1373 "%s: %s - Could not allocate mbuf\n",
1374 			__func__, USBDEVNAME(sc->sc_dev));
1375 
1376 		NG_UBT_STAT_IERROR(sc->sc_stat);
1377 		goto done;
1378 	}
1379 
1380 	/* Fix SCO data frame header if required */
1381 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1382 		*mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1383 		m->m_pkthdr.len = 1;
1384 		m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1385 	} else {
1386 		m->m_pkthdr.len = 0;
1387 		m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1388 	}
1389 
1390 	/*
1391 	 * XXX FIXME how do we know how many frames we have received?
1392 	 * XXX use frlen for now. is that correct?
1393 	 */
1394 
1395 	b = (u_int8_t *) sc->sc_isoc_in_buffer;
1396 
1397 	for (i = 0; i < sc->sc_isoc_nframes; i++) {
1398 		b += (i * sc->sc_isoc_size);
1399 
1400 		if (sc->sc_isoc_in_frlen[i] > 0)
1401 			m_copyback(m, m->m_pkthdr.len,
1402 				sc->sc_isoc_in_frlen[i], b);
1403 	}
1404 
1405 	if (m->m_pkthdr.len < sizeof(*hdr))
1406 		goto done;
1407 
1408 	hdr = mtod(m, ng_hci_scodata_pkt_t *);
1409 
1410 	if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1411 		NG_UBT_INFO(
1412 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1413 			__func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1414 			hdr->length);
1415 
1416 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1417 
1418 #if 0
1419 		NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1420 #endif
1421 		if (i != 0)
1422 			NG_UBT_STAT_IERROR(sc->sc_stat);
1423 	} else {
1424 		NG_UBT_ERR(
1425 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1426 			__func__, USBDEVNAME(sc->sc_dev), hdr->length,
1427 			m->m_pkthdr.len);
1428 
1429 		NG_UBT_STAT_IERROR(sc->sc_stat);
1430 		NG_FREE_M(m);
1431 	}
1432 done:
1433 	ubt_isoc_in_start(sc);
1434 } /* ubt_isoc_in_complete2 */
1435 
1436 /*
1437  * Start isochronous-out USB transfer. Must be called with node locked
1438  */
1439 
1440 Static usbd_status
ubt_isoc_out_start(struct ubt_softc * sc)1441 ubt_isoc_out_start(struct ubt_softc * sc)
1442 {
1443 	struct mbuf	*m = NULL;
1444 	u_int8_t	*b = NULL;
1445 	int		 i, len, nframes;
1446 	usbd_status	 status;
1447 
1448 	KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1449 "%s: %s - Another isoc-out request is pending\n",
1450 		__func__, USBDEVNAME(sc->sc_dev)));
1451 
1452 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1453 	if (m == NULL) {
1454 		NG_UBT_INFO(
1455 "%s: %s - SCO data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1456 
1457  		return (USBD_NORMAL_COMPLETION);
1458 	}
1459 
1460 	/* Copy entire SCO frame into USB transfer buffer and start transfer */
1461 	b = (u_int8_t *) sc->sc_isoc_out_buffer;
1462 	nframes = 0;
1463 
1464 	for (i = 0; i < sc->sc_isoc_nframes; i++) {
1465 		b += (i * sc->sc_isoc_size);
1466 
1467 		len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1468 		if (len > 0) {
1469 			m_copydata(m, 0, len, b);
1470 			m_adj(m, len);
1471 			nframes ++;
1472 		}
1473 
1474 		sc->sc_isoc_out_frlen[i] = len;
1475 	}
1476 
1477 	if (m->m_pkthdr.len > 0)
1478 		panic(
1479 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1480 			__func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_nframes,
1481 			sc->sc_isoc_size, m->m_pkthdr.len);
1482 
1483 	NG_FREE_M(m);
1484 
1485 	/* Initialize a isoc-out USB transfer and then schedule it */
1486 	usbd_setup_isoc_xfer(
1487 			sc->sc_isoc_out_xfer,
1488 			sc->sc_isoc_out_pipe,
1489 			(usbd_private_handle) sc,
1490 			sc->sc_isoc_out_frlen,
1491 			nframes,
1492 			USBD_NO_COPY,
1493 			ubt_isoc_out_complete);
1494 
1495 	status = usbd_transfer(sc->sc_isoc_out_xfer);
1496 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1497 		NG_UBT_ERR(
1498 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1499 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1500 			status);
1501 
1502 		NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1503 		NG_UBT_STAT_OERROR(sc->sc_stat);
1504 	} else {
1505 		NG_UBT_INFO(
1506 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1507 			__func__, USBDEVNAME(sc->sc_dev), nframes,
1508 			sc->sc_isoc_size);
1509 
1510 		sc->sc_flags |= UBT_SCO_XMIT;
1511 		status = USBD_NORMAL_COMPLETION;
1512 	}
1513 
1514 	return (status);
1515 } /* ubt_isoc_out_start */
1516 
1517 /*
1518  * USB isoc-out. transfer callback
1519  */
1520 Static void
ubt_isoc_out_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)1521 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1522 {
1523 	struct ubt_softc *	sc = p;
1524 
1525 	if (sc == NULL)
1526 		return;
1527 
1528 	KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1529 "%s: %s - No isoc-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1530 
1531 	sc->sc_flags &= ~UBT_SCO_XMIT;
1532 
1533 	if (s == USBD_CANCELLED) {
1534 		NG_UBT_INFO(
1535 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1536 			__func__, USBDEVNAME(sc->sc_dev),
1537 			sc->sc_isoc_out_pipe);
1538 
1539 		return;
1540 	}
1541 
1542 	if (s != USBD_NORMAL_COMPLETION) {
1543 		NG_UBT_WARN(
1544 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1545 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1546 
1547 		if (s == USBD_STALLED)
1548 			usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1549 
1550 		NG_UBT_STAT_OERROR(sc->sc_stat);
1551 	} else {
1552 		NG_UBT_INFO(
1553 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1554 			__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1555 
1556 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1557 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1558 	}
1559 
1560 	if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1561 		ubt_isoc_out_start(sc);
1562 } /* ubt_isoc_out_complete2 */
1563 
1564 /*
1565  * Abort transfers on all USB pipes
1566  */
1567 
1568 Static void
ubt_reset(struct ubt_softc * sc)1569 ubt_reset(struct ubt_softc * sc)
1570 {
1571 	/* Interrupt */
1572 	if (sc->sc_intr_pipe != NULL)
1573 		usbd_abort_pipe(sc->sc_intr_pipe);
1574 
1575 	/* Bulk-in/out */
1576 	if (sc->sc_bulk_in_pipe != NULL)
1577 		usbd_abort_pipe(sc->sc_bulk_in_pipe);
1578 	if (sc->sc_bulk_out_pipe != NULL)
1579 		usbd_abort_pipe(sc->sc_bulk_out_pipe);
1580 
1581 	/* Isoc-in/out */
1582 	if (sc->sc_isoc_in_pipe != NULL)
1583 		usbd_abort_pipe(sc->sc_isoc_in_pipe);
1584 	if (sc->sc_isoc_out_pipe != NULL)
1585 		usbd_abort_pipe(sc->sc_isoc_out_pipe);
1586 
1587 #if 0
1588 	/* Cleanup queues */
1589 	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1590 	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1591 	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1592 #endif
1593 } /* ubt_reset */
1594 
1595 /*
1596  * Process data
1597  */
1598 Static int
ubt_rcvdata(struct ubt_softc * sc,struct mbuf * m)1599 ubt_rcvdata(struct ubt_softc *sc, struct mbuf *m)
1600 {
1601 	usbd_status		(*f)(struct ubt_softc *) = NULL;
1602 	struct ng_bt_mbufq	*q = NULL;
1603 	int			 b, error = 0;
1604 
1605 	if (sc == NULL) {
1606 		error = EHOSTDOWN;
1607 		goto done;
1608 	}
1609 
1610 #if 0
1611 	if (hook != sc->sc_hook) {
1612 		error = EINVAL;
1613 		goto done;
1614 	}
1615 #endif
1616 
1617 #if 0
1618 	/* Deatch mbuf and get HCI frame type */
1619 	NGI_GET_M(item, m);
1620 #endif
1621 
1622 	/* Process HCI frame */
1623 	switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
1624 	case NG_HCI_CMD_PKT:
1625 		f = ubt_request_start;
1626 		q = &sc->sc_cmdq;
1627 		b = UBT_CMD_XMIT;
1628 		break;
1629 
1630 	case NG_HCI_ACL_DATA_PKT:
1631 		f = ubt_bulk_out_start;
1632 		q = &sc->sc_aclq;
1633 		b = UBT_ACL_XMIT;
1634 		break;
1635 
1636 #if __broken__ /* XXX FIXME */
1637 	case NG_HCI_SCO_DATA_PKT:
1638 		f = ubt_isoc_out_start;
1639 		q = &sc->sc_scoq;
1640 		b = UBT_SCO_XMIT;
1641 		break;
1642 #endif /* __broken__ */
1643 
1644 	default:
1645 		NG_UBT_ERR(
1646 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
1647 			__func__, USBDEVNAME(sc->sc_dev), *mtod(m, u_int8_t *),
1648 			m->m_pkthdr.len);
1649 
1650 		NG_FREE_M(m);
1651 		error = EINVAL;
1652 
1653 		goto done;
1654 		/* NOT REACHED */
1655 	}
1656 
1657 	/* Loose frame type, if required */
1658 	if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
1659 		m_adj(m, sizeof(u_int8_t));
1660 
1661 	if (NG_BT_MBUFQ_FULL(q)) {
1662 		NG_UBT_ERR(
1663 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
1664 			__func__, USBDEVNAME(sc->sc_dev),
1665 			*mtod(m, u_int8_t *), m->m_pkthdr.len);
1666 
1667 		NG_FREE_M(m);
1668 	} else
1669 		NG_BT_MBUFQ_ENQUEUE(q, m);
1670 
1671 	if (!(sc->sc_flags & b))
1672 		if ((*f)(sc) != USBD_NORMAL_COMPLETION)
1673 			error = EIO;
1674 done:
1675 #if 0
1676 	NG_FREE_ITEM(item);
1677 #endif
1678 
1679 	return (error);
1680 } /* ubt_rcvdata */
1681 
1682 void
ubt_stop(struct ubt_softc * sc)1683 ubt_stop(struct ubt_softc *sc)
1684 {
1685 	/* nothing yet */
1686 	return;
1687 }
1688 
1689 void
ubt_if_start(struct ifnet * ifp)1690 ubt_if_start(struct ifnet *ifp)
1691 {
1692 	struct ubt_softc *sc = ifp->if_softc;
1693 	struct mbuf *m0;
1694 
1695 	for (;;) {
1696 		IFQ_POLL(&ifp->if_snd, m0);
1697 		if (m0 == NULL)
1698 			break;
1699 
1700 		IFQ_DEQUEUE(&ifp->if_snd, m0);
1701 		ubt_rcvdata(sc, m0);
1702 	}
1703 }
1704 
1705 int
ubt_if_ioctl(struct ifnet * ifp,u_long command,caddr_t data)1706 ubt_if_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1707 {
1708 	struct ubt_softc *sc = ifp->if_softc;
1709 	struct ifreq *ifr = (struct ifreq *)data;
1710 	int s;
1711 	int error = 0;
1712 
1713 	s = splimp();
1714 	switch(command) {
1715 	case SIOCSIFADDR:
1716 		ifp->if_flags |= IFF_UP;
1717 		ubt_if_init(ifp);
1718 		break;
1719 	case SIOCSIFMTU:
1720 		if (ifr->ifr_mtu > 65536)
1721 			error = EINVAL;
1722 		ifp->if_mtu = ifr->ifr_mtu;
1723 		break;
1724 	case SIOCSIFFLAGS:
1725 		if (ifp->if_flags & IFF_UP) {
1726 			ubt_if_init(ifp);
1727 		} else {
1728 			if (ifp->if_flags & IFF_RUNNING)
1729 				ubt_stop(sc);
1730 		}
1731 		error = 0;
1732 		break;
1733 	default:
1734 		error = EINVAL;
1735 		break;
1736 	}
1737 	splx(s);
1738 
1739 	return(error);
1740 }
1741 
1742 int
ubt_if_init(struct ifnet * ifp)1743 ubt_if_init(struct ifnet *ifp)
1744 {
1745 	/* nothing yet */
1746 	return (0);
1747 }
1748 
1749 void
ubt_if_watchdog(struct ifnet * ifp)1750 ubt_if_watchdog(struct ifnet *ifp)
1751 {
1752 	/* nothing yet */
1753 	return;
1754 }
1755