1 /*
2  * ng_ubt.c
3  */
4 
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: ng_ubt.c,v 1.16 2003/10/10 19:15:06 max Exp $
31  * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c,v 1.33 2007/06/23 04:34:38 imp Exp $
32  * $DragonFly: src/sys/netgraph7/bluetooth/drivers/ubt/ng_ubt.c,v 1.2 2008/06/26 23:05:40 dillon Exp $
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/conf.h>
39 #include <sys/endian.h>
40 #include <sys/filio.h>
41 #include <sys/fcntl.h>
42 #include <sys/mbuf.h>
43 #include <sys/malloc.h>
44 #include <sys/kernel.h>
45 #include <sys/module.h>
46 #include <sys/poll.h>
47 #include <sys/uio.h>
48 #include <machine/bus.h>
49 
50 #include <dev/usb/usb.h>
51 #include <dev/usb/usbdi.h>
52 #include <dev/usb/usbdi_util.h>
53 #include <dev/usb/usbdivar.h>
54 
55 #include "ng_message.h"
56 #include "netgraph.h"
57 #include "ng_parse.h"
58 #include "bluetooth/include/ng_bluetooth.h"
59 #include "bluetooth/include/ng_hci.h"
60 #include "bluetooth/include/ng_ubt.h"
61 #include "bluetooth/drivers/ubt/ng_ubt_var.h"
62 
63 #include "usbdevs.h"
64 
65 /*
66  * USB methods
67  */
68 
69 static device_probe_t ubt_match;
70 static device_attach_t ubt_attach;
71 static device_detach_t ubt_detach;
72 
73 static device_method_t ubt_methods[] = {
74 	/* Device interface */
75 	DEVMETHOD(device_probe,		ubt_match),
76 	DEVMETHOD(device_attach,	ubt_attach),
77 	DEVMETHOD(device_detach,	ubt_detach),
78 
79 	{ 0, 0 }
80 };
81 
82 static driver_t ubt_driver = {
83 	"ubt",
84 	ubt_methods,
85 	sizeof(struct ubt_softc)
86 };
87 
88 static devclass_t ubt_devclass;
89 
90 static int         ubt_modevent		  (module_t, int, void *);
91 
92 static usbd_status ubt_request_start      (ubt_softc_p);
93 static void        ubt_request_complete   (usbd_xfer_handle,
94 					   usbd_private_handle, usbd_status);
95 static void        ubt_request_complete2  (node_p, hook_p, void *, int);
96 
97 static usbd_status ubt_intr_start	  (ubt_softc_p);
98 static void        ubt_intr_complete      (usbd_xfer_handle,
99 					   usbd_private_handle, usbd_status);
100 static void        ubt_intr_complete2     (node_p, hook_p, void *, int);
101 
102 static usbd_status ubt_bulk_in_start	  (ubt_softc_p);
103 static void        ubt_bulk_in_complete   (usbd_xfer_handle,
104 					   usbd_private_handle, usbd_status);
105 static void        ubt_bulk_in_complete2  (node_p, hook_p, void *, int);
106 
107 static usbd_status ubt_bulk_out_start     (ubt_softc_p);
108 static void        ubt_bulk_out_complete  (usbd_xfer_handle,
109 					   usbd_private_handle, usbd_status);
110 static void        ubt_bulk_out_complete2 (node_p, hook_p, void *, int);
111 
112 static usbd_status ubt_isoc_in_start      (ubt_softc_p);
113 static void        ubt_isoc_in_complete   (usbd_xfer_handle,
114 					   usbd_private_handle, usbd_status);
115 static void        ubt_isoc_in_complete2  (node_p, hook_p, void *, int);
116 
117 static usbd_status ubt_isoc_out_start     (ubt_softc_p);
118 static void        ubt_isoc_out_complete  (usbd_xfer_handle,
119 					   usbd_private_handle, usbd_status);
120 static void        ubt_isoc_out_complete2 (node_p, hook_p, void *, int);
121 
122 static void        ubt_reset              (ubt_softc_p);
123 
124 /*
125  * Netgraph methods
126  */
127 
128 static ng_constructor_t	ng_ubt_constructor;
129 static ng_shutdown_t	ng_ubt_shutdown;
130 static ng_newhook_t	ng_ubt_newhook;
131 static ng_connect_t	ng_ubt_connect;
132 static ng_disconnect_t	ng_ubt_disconnect;
133 static ng_rcvmsg_t	ng_ubt_rcvmsg;
134 static ng_rcvdata_t	ng_ubt_rcvdata;
135 
136 /* Queue length */
137 static const struct ng_parse_struct_field	ng_ubt_node_qlen_type_fields[] =
138 {
139 	{ "queue", &ng_parse_int32_type, },
140 	{ "qlen",  &ng_parse_int32_type, },
141 	{ NULL, }
142 };
143 static const struct ng_parse_type		ng_ubt_node_qlen_type = {
144 	&ng_parse_struct_type,
145 	&ng_ubt_node_qlen_type_fields
146 };
147 
148 /* Stat info */
149 static const struct ng_parse_struct_field	ng_ubt_node_stat_type_fields[] =
150 {
151 	{ "pckts_recv", &ng_parse_uint32_type, },
152 	{ "bytes_recv", &ng_parse_uint32_type, },
153 	{ "pckts_sent", &ng_parse_uint32_type, },
154 	{ "bytes_sent", &ng_parse_uint32_type, },
155 	{ "oerrors",    &ng_parse_uint32_type, },
156 	{ "ierrors",    &ng_parse_uint32_type, },
157 	{ NULL, }
158 };
159 static const struct ng_parse_type	ng_ubt_node_stat_type = {
160 	&ng_parse_struct_type,
161 	&ng_ubt_node_stat_type_fields
162 };
163 
164 /* Netgraph node command list */
165 static const struct ng_cmdlist	ng_ubt_cmdlist[] = {
166 {
167 	NGM_UBT_COOKIE,
168 	NGM_UBT_NODE_SET_DEBUG,
169 	"set_debug",
170 	&ng_parse_uint16_type,
171 	NULL
172 },
173 {
174 	NGM_UBT_COOKIE,
175 	NGM_UBT_NODE_GET_DEBUG,
176 	"get_debug",
177 	NULL,
178 	&ng_parse_uint16_type
179 },
180 {
181 	NGM_UBT_COOKIE,
182 	NGM_UBT_NODE_SET_QLEN,
183 	"set_qlen",
184 	&ng_ubt_node_qlen_type,
185 	NULL
186 },
187 {
188 	NGM_UBT_COOKIE,
189 	NGM_UBT_NODE_GET_QLEN,
190 	"get_qlen",
191 	&ng_ubt_node_qlen_type,
192 	&ng_ubt_node_qlen_type
193 },
194 {
195 	NGM_UBT_COOKIE,
196 	NGM_UBT_NODE_GET_STAT,
197 	"get_stat",
198 	NULL,
199 	&ng_ubt_node_stat_type
200 },
201 {
202 	NGM_UBT_COOKIE,
203 	NGM_UBT_NODE_RESET_STAT,
204 	"reset_stat",
205         NULL,
206 	NULL
207 },
208 { 0, }
209 };
210 
211 /* Netgraph node type */
212 static struct ng_type	typestruct = {
213 	.version =	NG_ABI_VERSION,
214 	.name =		NG_UBT_NODE_TYPE,
215 	.constructor =	ng_ubt_constructor,
216 	.rcvmsg =	ng_ubt_rcvmsg,
217 	.shutdown =	ng_ubt_shutdown,
218 	.newhook =	ng_ubt_newhook,
219 	.connect =	ng_ubt_connect,
220 	.rcvdata =	ng_ubt_rcvdata,
221 	.disconnect =	ng_ubt_disconnect,
222 	.cmdlist =	ng_ubt_cmdlist
223 };
224 
225 /*
226  * Module
227  */
228 
229 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
230 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
231 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
232 MODULE_DEPEND(ubt, usb, 1, 1, 1);
233 
234 
235 /****************************************************************************
236  ****************************************************************************
237  **                              USB specific
238  ****************************************************************************
239  ****************************************************************************/
240 
241 /*
242  * Load/Unload the driver module
243  */
244 
245 static int
246 ubt_modevent(module_t mod, int event, void *data)
247 {
248 	int	error;
249 
250 	switch (event) {
251 	case MOD_LOAD:
252 		error = ng_newtype(&typestruct);
253 		if (error != 0)
254 			printf(
255 "%s: Could not register Netgraph node type, error=%d\n",
256 				NG_UBT_NODE_TYPE, error);
257 		else
258 			error = usbd_driver_load(mod, event, data);
259 		break;
260 
261 	case MOD_UNLOAD:
262 		error = ng_rmtype(&typestruct);
263 		if (error == 0)
264 			error = usbd_driver_load(mod, event, data);
265 		break;
266 
267 	default:
268 		error = EOPNOTSUPP;
269 		break;
270 	}
271 
272 	return (error);
273 } /* ubt_modevent */
274 
275 /*
276  * Probe for a USB Bluetooth device
277  */
278 
279 static int
280 ubt_match(device_t self)
281 {
282 	/*
283 	 * If for some reason device should not be attached then put
284 	 * VendorID/ProductID pair into the list below. The format is
285 	 * as follows:
286 	 *
287 	 *	{ VENDOR_ID, PRODUCT_ID },
288 	 *
289 	 * where VENDOR_ID and PRODUCT_ID are hex numbers.
290 	 */
291 
292 	static struct usb_devno const	ubt_ignored_devices[] = {
293 		{ USB_VENDOR_AVM, 0x2200 }, /* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */
294 		{ 0, 0 } /* This should be the last item in the list */
295 	};
296 
297 	/*
298 	 * If device violates Bluetooth specification and has bDeviceClass,
299 	 * bDeviceSubClass and bDeviceProtocol set to wrong values then you
300 	 * could try to put VendorID/ProductID pair into the list below.
301 	 * Adding VendorID/ProductID pair into this list forces ng_ubt(4)
302 	 * to attach to the broken device.
303 	 */
304 
305 	static struct usb_devno const	ubt_broken_devices[] = {
306 		{ USB_VENDOR_AVM, 0x3800 }, /* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
307 		{ 0, 0 } /* This should be the last item in the list */
308 	};
309 
310 	struct usb_attach_arg *uaa = device_get_ivars(self);
311 	usb_device_descriptor_t	*dd = usbd_get_device_descriptor(uaa->device);
312 
313 	if (uaa->iface == NULL ||
314 	    usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
315 		return (UMATCH_NONE);
316 
317 	if (dd->bDeviceClass == UDCLASS_WIRELESS &&
318 	    dd->bDeviceSubClass == UDSUBCLASS_RF &&
319 	    dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
320 		return (UMATCH_DEVCLASS_DEVSUBCLASS);
321 
322 	if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
323 		return (UMATCH_VENDOR_PRODUCT);
324 
325 	return (UMATCH_NONE);
326 } /* ubt_match */
327 
328 /*
329  * Attach the device
330  */
331 
332 static int
333 ubt_attach(device_t self)
334 {
335 	struct ubt_softc *sc = device_get_softc(self);
336 	struct usb_attach_arg *uaa = device_get_ivars(self);
337 	usb_config_descriptor_t		*cd = NULL;
338 	usb_interface_descriptor_t	*id = NULL;
339 	usb_endpoint_descriptor_t	*ed = NULL;
340 	usbd_status			 error;
341 	int				 i, ai, alt_no, isoc_in, isoc_out,
342 					 isoc_isize, isoc_osize;
343 
344 	/* Get USB device info */
345 	sc->sc_dev = self;
346 	sc->sc_udev = uaa->device;
347 
348 	/*
349 	 * Initialize device softc structure
350 	 */
351 
352 	/* State */
353 	sc->sc_debug = NG_UBT_WARN_LEVEL;
354 	sc->sc_flags = 0;
355 	NG_UBT_STAT_RESET(sc->sc_stat);
356 
357 	/* Interfaces */
358 	sc->sc_iface0 = sc->sc_iface1 = NULL;
359 
360 	/* Interrupt pipe */
361 	sc->sc_intr_ep = -1;
362 	sc->sc_intr_pipe = NULL;
363 	sc->sc_intr_xfer = NULL;
364 	sc->sc_intr_buffer = NULL;
365 
366 	/* Control pipe */
367 	sc->sc_ctrl_xfer = NULL;
368 	sc->sc_ctrl_buffer = NULL;
369 	NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
370 
371 	/* Bulk-in pipe */
372 	sc->sc_bulk_in_ep = -1;
373 	sc->sc_bulk_in_pipe = NULL;
374 	sc->sc_bulk_in_xfer = NULL;
375 	sc->sc_bulk_in_buffer = NULL;
376 
377 	/* Bulk-out pipe */
378 	sc->sc_bulk_out_ep = -1;
379 	sc->sc_bulk_out_pipe = NULL;
380 	sc->sc_bulk_out_xfer = NULL;
381 	sc->sc_bulk_out_buffer = NULL;
382 	NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
383 
384 	/* Isoc-in pipe */
385 	sc->sc_isoc_in_ep = -1;
386 	sc->sc_isoc_in_pipe = NULL;
387 	sc->sc_isoc_in_xfer = NULL;
388 
389 	/* Isoc-out pipe */
390 	sc->sc_isoc_out_ep = -1;
391 	sc->sc_isoc_out_pipe = NULL;
392 	sc->sc_isoc_out_xfer = NULL;
393 	sc->sc_isoc_size = -1;
394 	NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
395 
396 	/* Netgraph part */
397 	sc->sc_node = NULL;
398 	sc->sc_hook = NULL;
399 
400 	/*
401 	 * XXX set configuration?
402 	 *
403 	 * Configure Bluetooth USB device. Discover all required USB interfaces
404 	 * and endpoints.
405 	 *
406 	 * USB device must present two interfaces:
407 	 * 1) Interface 0 that has 3 endpoints
408 	 *	1) Interrupt endpoint to receive HCI events
409 	 *	2) Bulk IN endpoint to receive ACL data
410 	 *	3) Bulk OUT endpoint to send ACL data
411 	 *
412 	 * 2) Interface 1 then has 2 endpoints
413 	 *	1) Isochronous IN endpoint to receive SCO data
414  	 *	2) Isochronous OUT endpoint to send SCO data
415 	 *
416 	 * Interface 1 (with isochronous endpoints) has several alternate
417 	 * configurations with different packet size.
418 	 */
419 
420 	/*
421 	 * Interface 0
422 	 */
423 
424 	error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
425 	if (error || sc->sc_iface0 == NULL) {
426 		printf("%s: Could not get interface 0 handle. %s (%d), " \
427 			"handle=%p\n", device_get_nameunit(sc->sc_dev),
428 			usbd_errstr(error), error, sc->sc_iface0);
429 		goto bad;
430 	}
431 
432 	id = usbd_get_interface_descriptor(sc->sc_iface0);
433 	if (id == NULL) {
434 		printf("%s: Could not get interface 0 descriptor\n",
435 			device_get_nameunit(sc->sc_dev));
436 		goto bad;
437 	}
438 
439 	for (i = 0; i < id->bNumEndpoints; i ++) {
440 		ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
441 		if (ed == NULL) {
442 			printf("%s: Could not read endpoint descriptor for " \
443 				"interface 0, i=%d\n", device_get_nameunit(sc->sc_dev),
444 				i);
445 			goto bad;
446 		}
447 
448 		switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
449 		case UE_BULK:
450 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
451 				sc->sc_bulk_in_ep = ed->bEndpointAddress;
452 			else
453 				sc->sc_bulk_out_ep = ed->bEndpointAddress;
454 			break;
455 
456 		case UE_INTERRUPT:
457 			sc->sc_intr_ep = ed->bEndpointAddress;
458 			break;
459 		}
460 	}
461 
462 	/* Check if we got everything we wanted on Interface 0 */
463 	if (sc->sc_intr_ep == -1) {
464 		printf("%s: Could not detect interrupt endpoint\n",
465 			device_get_nameunit(sc->sc_dev));
466 		goto bad;
467 	}
468 	if (sc->sc_bulk_in_ep == -1) {
469 		printf("%s: Could not detect bulk-in endpoint\n",
470 			device_get_nameunit(sc->sc_dev));
471 		goto bad;
472 	}
473 	if (sc->sc_bulk_out_ep == -1) {
474 		printf("%s: Could not detect bulk-out endpoint\n",
475 			device_get_nameunit(sc->sc_dev));
476 		goto bad;
477 	}
478 
479 	printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
480 		"bulk-out=%#x\n", device_get_nameunit(sc->sc_dev),
481 		sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
482 
483 	/*
484 	 * Interface 1
485 	 */
486 
487 	cd = usbd_get_config_descriptor(sc->sc_udev);
488 	if (cd == NULL) {
489 		printf("%s: Could not get device configuration descriptor\n",
490 			device_get_nameunit(sc->sc_dev));
491 		goto bad;
492 	}
493 
494 	error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
495 	if (error || sc->sc_iface1 == NULL) {
496 		printf("%s: Could not get interface 1 handle. %s (%d), " \
497 			"handle=%p\n", device_get_nameunit(sc->sc_dev),
498 			usbd_errstr(error), error, sc->sc_iface1);
499 		goto bad;
500 	}
501 
502 	id = usbd_get_interface_descriptor(sc->sc_iface1);
503 	if (id == NULL) {
504 		printf("%s: Could not get interface 1 descriptor\n",
505 			device_get_nameunit(sc->sc_dev));
506 		goto bad;
507 	}
508 
509 	/*
510 	 * Scan all alternate configurations for interface 1
511 	 */
512 
513 	alt_no = -1;
514 
515 	for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++)  {
516 		error = usbd_set_interface(sc->sc_iface1, ai);
517 		if (error) {
518 			printf("%s: [SCAN] Could not set alternate " \
519 				"configuration %d for interface 1. %s (%d)\n",
520 				device_get_nameunit(sc->sc_dev),  ai, usbd_errstr(error),
521 				error);
522 			goto bad;
523 		}
524 		id = usbd_get_interface_descriptor(sc->sc_iface1);
525 		if (id == NULL) {
526 			printf("%s: Could not get interface 1 descriptor for " \
527 				"alternate configuration %d\n",
528 				device_get_nameunit(sc->sc_dev), ai);
529 			goto bad;
530 		}
531 
532 		isoc_in = isoc_out = -1;
533 		isoc_isize = isoc_osize = 0;
534 
535 		for (i = 0; i < id->bNumEndpoints; i ++) {
536 			ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
537 			if (ed == NULL) {
538 				printf("%s: Could not read endpoint " \
539 					"descriptor for interface 1, " \
540 					"alternate configuration %d, i=%d\n",
541 					device_get_nameunit(sc->sc_dev), ai, i);
542 				goto bad;
543 			}
544 
545 			if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
546 				continue;
547 
548 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
549 				isoc_in = ed->bEndpointAddress;
550 				isoc_isize = UGETW(ed->wMaxPacketSize);
551 			} else {
552 				isoc_out = ed->bEndpointAddress;
553 				isoc_osize = UGETW(ed->wMaxPacketSize);
554 			}
555 		}
556 
557 		/*
558 		 * Make sure that configuration looks sane and if so
559 		 * update current settings
560 		 */
561 
562 		if (isoc_in != -1 && isoc_out != -1 &&
563 		    isoc_isize > 0  && isoc_osize > 0 &&
564 		    isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
565 			sc->sc_isoc_in_ep = isoc_in;
566 			sc->sc_isoc_out_ep = isoc_out;
567 			sc->sc_isoc_size = isoc_isize;
568 			alt_no = ai;
569 		}
570 	}
571 
572 	/* Check if we got everything we wanted on Interface 0 */
573 	if (sc->sc_isoc_in_ep == -1) {
574 		printf("%s: Could not detect isoc-in endpoint\n",
575 			device_get_nameunit(sc->sc_dev));
576 		goto bad;
577 	}
578 	if (sc->sc_isoc_out_ep == -1) {
579 		printf("%s: Could not detect isoc-out endpoint\n",
580 			device_get_nameunit(sc->sc_dev));
581 		goto bad;
582 	}
583 	if (sc->sc_isoc_size <= 0) {
584 		printf("%s: Invalid isoc. packet size=%d\n",
585 			device_get_nameunit(sc->sc_dev), sc->sc_isoc_size);
586 		goto bad;
587 	}
588 
589 	error = usbd_set_interface(sc->sc_iface1, alt_no);
590 	if (error) {
591 		printf("%s: Could not set alternate configuration " \
592 			"%d for interface 1. %s (%d)\n", device_get_nameunit(sc->sc_dev),
593 			alt_no, usbd_errstr(error), error);
594 		goto bad;
595 	}
596 
597 	/* Allocate USB transfer handles and buffers */
598 	sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
599 	if (sc->sc_ctrl_xfer == NULL) {
600 		printf("%s: Could not allocate control xfer handle\n",
601 			device_get_nameunit(sc->sc_dev));
602 		goto bad;
603 	}
604 	sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
605 						UBT_CTRL_BUFFER_SIZE);
606 	if (sc->sc_ctrl_buffer == NULL) {
607 		printf("%s: Could not allocate control buffer\n",
608 			device_get_nameunit(sc->sc_dev));
609 		goto bad;
610 	}
611 
612 	sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
613 	if (sc->sc_intr_xfer == NULL) {
614 		printf("%s: Could not allocate interrupt xfer handle\n",
615 			device_get_nameunit(sc->sc_dev));
616 		goto bad;
617 	}
618 
619 	sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
620 	if (sc->sc_bulk_in_xfer == NULL) {
621 		printf("%s: Could not allocate bulk-in xfer handle\n",
622 			device_get_nameunit(sc->sc_dev));
623 		goto bad;
624 	}
625 
626 	sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
627 	if (sc->sc_bulk_out_xfer == NULL) {
628 		printf("%s: Could not allocate bulk-out xfer handle\n",
629 			device_get_nameunit(sc->sc_dev));
630 		goto bad;
631 	}
632 	sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
633 						UBT_BULK_BUFFER_SIZE);
634 	if (sc->sc_bulk_out_buffer == NULL) {
635 		printf("%s: Could not allocate bulk-out buffer\n",
636 			device_get_nameunit(sc->sc_dev));
637 		goto bad;
638 	}
639 
640 	/*
641 	 * Allocate buffers for isoc. transfers
642 	 */
643 
644 	sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
645 
646 	sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
647 	if (sc->sc_isoc_in_xfer == NULL) {
648 		printf("%s: Could not allocate isoc-in xfer handle\n",
649 			device_get_nameunit(sc->sc_dev));
650 		goto bad;
651 	}
652 	sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
653 					sc->sc_isoc_nframes * sc->sc_isoc_size);
654 	if (sc->sc_isoc_in_buffer == NULL) {
655 		printf("%s: Could not allocate isoc-in buffer\n",
656 			device_get_nameunit(sc->sc_dev));
657 		goto bad;
658 	}
659 	sc->sc_isoc_in_frlen = kmalloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
660 						M_USBDEV, M_WAITOK | M_NULLOK);
661 	if (sc->sc_isoc_in_frlen == NULL) {
662 		printf("%s: Could not allocate isoc-in frame sizes buffer\n",
663 			device_get_nameunit(sc->sc_dev));
664 		goto bad;
665 	}
666 
667 	sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
668 	if (sc->sc_isoc_out_xfer == NULL) {
669 		printf("%s: Could not allocate isoc-out xfer handle\n",
670 			device_get_nameunit(sc->sc_dev));
671 		goto bad;
672 	}
673 	sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
674 					sc->sc_isoc_nframes * sc->sc_isoc_size);
675 	if (sc->sc_isoc_out_buffer == NULL) {
676 		printf("%s: Could not allocate isoc-out buffer\n",
677 			device_get_nameunit(sc->sc_dev));
678 		goto bad;
679 	}
680 	sc->sc_isoc_out_frlen = kmalloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
681 						M_USBDEV, M_WAITOK | M_NULLOK);
682 	if (sc->sc_isoc_out_frlen == NULL) {
683 		printf("%s: Could not allocate isoc-out frame sizes buffer\n",
684 			device_get_nameunit(sc->sc_dev));
685 		goto bad;
686 	}
687 
688 	printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
689 		"isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
690 		device_get_nameunit(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
691 		sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes,
692 		(sc->sc_isoc_nframes * sc->sc_isoc_size));
693 
694 	/*
695 	 * Open pipes
696 	 */
697 
698 	/* Interrupt */
699 	error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
700 			USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
701 	if (error != USBD_NORMAL_COMPLETION) {
702 		printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
703 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
704 			error);
705 		goto bad;
706 	}
707 
708 	/* Bulk-in */
709 	error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
710 			USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
711 	if (error != USBD_NORMAL_COMPLETION) {
712 		printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
713 			__func__,  device_get_nameunit(sc->sc_dev), usbd_errstr(error),
714 			error);
715 		goto bad;
716 	}
717 
718 	/* Bulk-out */
719 	error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
720 			USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
721 	if (error != USBD_NORMAL_COMPLETION) {
722 		printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
723 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
724 			error);
725 		goto bad;
726 	}
727 
728 #if 0 /* XXX FIXME */
729 	/* Isoc-in */
730 	error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
731 			USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
732 	if (error != USBD_NORMAL_COMPLETION) {
733 		printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
734 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
735 			error);
736 		goto bad;
737 	}
738 
739 	/* Isoc-out */
740 	error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
741 			USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
742 	if (error != USBD_NORMAL_COMPLETION) {
743 		printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
744 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
745 			error);
746 		goto bad;
747 	}
748 #endif
749 
750 	/* Create Netgraph node */
751 	if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
752 		printf("%s: Could not create Netgraph node\n",
753 			device_get_nameunit(sc->sc_dev));
754 		sc->sc_node = NULL;
755 		goto bad;
756 	}
757 
758 	/* Name node */
759 	if (ng_name_node(sc->sc_node, device_get_nameunit(sc->sc_dev)) != 0) {
760 		printf("%s: Could not name Netgraph node\n",
761 			device_get_nameunit(sc->sc_dev));
762 		NG_NODE_UNREF(sc->sc_node);
763 		sc->sc_node = NULL;
764 		goto bad;
765 	}
766 
767 	NG_NODE_SET_PRIVATE(sc->sc_node, sc);
768 	NG_NODE_FORCE_WRITER(sc->sc_node);
769 
770 	/* Claim all interfaces on the device */
771 	for (i = 0; i < uaa->nifaces; i++)
772 		uaa->ifaces[i] = NULL;
773 
774 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
775 		sc->sc_dev);
776 
777 	return 0;
778 bad:
779 	ubt_detach(self);
780 
781 	return ENXIO;
782 } /* ubt_attach */
783 
784 /*
785  * Detach the device
786  */
787 
788 static int
789 ubt_detach(device_t self)
790 {
791 	struct ubt_softc *sc = device_get_softc(self);
792 
793 	/* Destroy Netgraph node */
794 	if (sc->sc_node != NULL) {
795 		NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
796 		ng_rmnode_self(sc->sc_node);
797 		sc->sc_node = NULL;
798 	}
799 
800 	/* Close pipes */
801 	if (sc->sc_intr_pipe != NULL) {
802 		usbd_close_pipe(sc->sc_intr_pipe);
803 		sc->sc_intr_pipe = NULL;
804 	}
805 
806 	if (sc->sc_bulk_in_pipe != NULL) {
807 		usbd_close_pipe(sc->sc_bulk_in_pipe);
808 		sc->sc_bulk_in_pipe = NULL;
809 	}
810 	if (sc->sc_bulk_out_pipe != NULL) {
811 		usbd_close_pipe(sc->sc_bulk_out_pipe);
812 		sc->sc_bulk_out_pipe = NULL;
813 	}
814 
815 	if (sc->sc_isoc_in_pipe != NULL) {
816 		usbd_close_pipe(sc->sc_isoc_in_pipe);
817 		sc->sc_isoc_in_pipe = NULL;
818 	}
819 	if (sc->sc_isoc_out_pipe != NULL) {
820 		usbd_close_pipe(sc->sc_isoc_out_pipe);
821 		sc->sc_isoc_out_pipe = NULL;
822 	}
823 
824 	/* Destroy USB transfer handles */
825 	if (sc->sc_ctrl_xfer != NULL) {
826 		usbd_free_xfer(sc->sc_ctrl_xfer);
827 		sc->sc_ctrl_xfer = NULL;
828 	}
829 
830 	if (sc->sc_intr_xfer != NULL) {
831 		usbd_free_xfer(sc->sc_intr_xfer);
832 		sc->sc_intr_xfer = NULL;
833 	}
834 
835 	if (sc->sc_bulk_in_xfer != NULL) {
836 		usbd_free_xfer(sc->sc_bulk_in_xfer);
837 		sc->sc_bulk_in_xfer = NULL;
838 	}
839 	if (sc->sc_bulk_out_xfer != NULL) {
840 		usbd_free_xfer(sc->sc_bulk_out_xfer);
841 		sc->sc_bulk_out_xfer = NULL;
842 	}
843 
844 	if (sc->sc_isoc_in_xfer != NULL) {
845 		usbd_free_xfer(sc->sc_isoc_in_xfer);
846 		sc->sc_isoc_in_xfer = NULL;
847 	}
848 	if (sc->sc_isoc_out_xfer != NULL) {
849 		usbd_free_xfer(sc->sc_isoc_out_xfer);
850 		sc->sc_isoc_out_xfer = NULL;
851 	}
852 
853 	/* Destroy isoc. frame size buffers */
854 	if (sc->sc_isoc_in_frlen != NULL) {
855 		kfree(sc->sc_isoc_in_frlen, M_USBDEV);
856 		sc->sc_isoc_in_frlen = NULL;
857 	}
858 	if (sc->sc_isoc_out_frlen != NULL) {
859 		kfree(sc->sc_isoc_out_frlen, M_USBDEV);
860 		sc->sc_isoc_out_frlen = NULL;
861 	}
862 
863 	/* Destroy queues */
864 	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
865 	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
866 	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
867 
868 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
869 			sc->sc_dev);
870 
871 	return (0);
872 } /* ubt_detach */
873 
874 /*
875  * Start USB control request (HCI command). Must be called with node locked
876  */
877 
878 static usbd_status
879 ubt_request_start(ubt_softc_p sc)
880 {
881 	usb_device_request_t	 req;
882 	struct mbuf		*m = NULL;
883 	usbd_status		 status;
884 
885 	KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
886 "%s: %s - Another control request is pending\n",
887 		__func__, device_get_nameunit(sc->sc_dev)));
888 
889 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
890 	if (m == NULL) {
891 		NG_UBT_INFO(
892 "%s: %s - HCI command queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
893 
894 		return (USBD_NORMAL_COMPLETION);
895 	}
896 
897 	/*
898 	 * Check HCI command frame size and copy it back to
899 	 * linear USB transfer buffer.
900 	 */
901 
902 	if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
903 		panic(
904 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
905 			__func__, device_get_nameunit(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
906 			m->m_pkthdr.len);
907 
908 	m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
909 
910 	/* Initialize a USB control request and then schedule it */
911 	bzero(&req, sizeof(req));
912 	req.bmRequestType = UBT_HCI_REQUEST;
913 	USETW(req.wLength, m->m_pkthdr.len);
914 
915 	NG_UBT_INFO(
916 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
917 		__func__, device_get_nameunit(sc->sc_dev), req.bmRequestType,
918 		UGETW(req.wLength));
919 
920 	usbd_setup_default_xfer(
921 		sc->sc_ctrl_xfer,
922 		sc->sc_udev,
923 		(usbd_private_handle) sc->sc_node,
924 		USBD_DEFAULT_TIMEOUT, /* XXX */
925 		&req,
926 		sc->sc_ctrl_buffer,
927 		m->m_pkthdr.len,
928 		USBD_NO_COPY,
929 		ubt_request_complete);
930 
931 	NG_NODE_REF(sc->sc_node);
932 
933 	status = usbd_transfer(sc->sc_ctrl_xfer);
934 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
935 		NG_UBT_ERR(
936 "%s: %s - Could not start control request. %s (%d)\n",
937 			__func__, device_get_nameunit(sc->sc_dev),
938 			usbd_errstr(status), status);
939 
940 		NG_NODE_UNREF(sc->sc_node);
941 
942 		NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
943 		NG_UBT_STAT_OERROR(sc->sc_stat);
944 
945 		/* XXX FIXME should we try to resubmit another request? */
946 	} else {
947 		NG_UBT_INFO(
948 "%s: %s - Control request has been started\n",
949 			__func__, device_get_nameunit(sc->sc_dev));
950 
951 		sc->sc_flags |= UBT_CMD_XMIT;
952 		status = USBD_NORMAL_COMPLETION;
953 	}
954 
955 	NG_FREE_M(m);
956 
957 	return (status);
958 } /* ubt_request_start */
959 
960 /*
961  * USB control request callback
962  */
963 
964 static void
965 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
966 {
967 	ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
968 	NG_NODE_UNREF((node_p) p);
969 } /* ubt_request_complete */
970 
971 static void
972 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
973 {
974 	ubt_softc_p		sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
975 	usbd_xfer_handle	h = (usbd_xfer_handle) arg1;
976 	usbd_status		s = (usbd_status) arg2;
977 
978 	if (sc == NULL)
979 		return;
980 
981 	KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
982 "%s: %s - No control request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
983 
984 	sc->sc_flags &= ~UBT_CMD_XMIT;
985 
986 	if (s == USBD_CANCELLED) {
987 		NG_UBT_INFO(
988 "%s: %s - Control request cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
989 
990 		return;
991 	}
992 
993 	if (s != USBD_NORMAL_COMPLETION) {
994 		NG_UBT_ERR(
995 "%s: %s - Control request failed. %s (%d)\n",
996 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
997 
998 		if (s == USBD_STALLED)
999 			usbd_clear_endpoint_stall_async(h->pipe);
1000 
1001 		NG_UBT_STAT_OERROR(sc->sc_stat);
1002 	} else {
1003 		NG_UBT_INFO(
1004 "%s: %s - Sent %d bytes to control pipe\n",
1005 			__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1006 
1007 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1008 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1009 	}
1010 
1011 	if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
1012 		ubt_request_start(sc);
1013 } /* ubt_request_complete2 */
1014 
1015 /*
1016  * Start interrupt transfer. Must be called when node is locked
1017  */
1018 
1019 static usbd_status
1020 ubt_intr_start(ubt_softc_p sc)
1021 {
1022 	struct mbuf	*m = NULL;
1023 	usbd_status	 status;
1024 
1025 	KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
1026 "%s: %s - Another interrupt request is pending\n",
1027 		__func__, device_get_nameunit(sc->sc_dev)));
1028 
1029 	/* Allocate new mbuf cluster */
1030 	MGETHDR(m, MB_DONTWAIT, MT_DATA);
1031 	if (m == NULL)
1032 		return (USBD_NOMEM);
1033 
1034 	MCLGET(m, MB_DONTWAIT);
1035 	if (!(m->m_flags & M_EXT)) {
1036 		NG_FREE_M(m);
1037 		return (USBD_NOMEM);
1038 	}
1039 
1040 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1041 		*mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
1042 		m->m_pkthdr.len = m->m_len = 1;
1043 	} else
1044 		m->m_pkthdr.len = m->m_len = 0;
1045 
1046 	/* Initialize a USB transfer and then schedule it */
1047 	usbd_setup_xfer(
1048 			sc->sc_intr_xfer,
1049 			sc->sc_intr_pipe,
1050 			(usbd_private_handle) sc->sc_node,
1051 			(void *)(mtod(m, u_int8_t *) + m->m_len),
1052 			MCLBYTES - m->m_len,
1053 			USBD_SHORT_XFER_OK,
1054 			USBD_NO_TIMEOUT,
1055 			ubt_intr_complete);
1056 
1057 	NG_NODE_REF(sc->sc_node);
1058 
1059 	status = usbd_transfer(sc->sc_intr_xfer);
1060 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1061 		NG_UBT_ERR(
1062 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1063 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1064 			status);
1065 
1066 		NG_NODE_UNREF(sc->sc_node);
1067 
1068 		NG_FREE_M(m);
1069 
1070 		return (status);
1071 	}
1072 
1073 	sc->sc_flags |= UBT_EVT_RECV;
1074 	sc->sc_intr_buffer = m;
1075 
1076 	return (USBD_NORMAL_COMPLETION);
1077 } /* ubt_intr_start */
1078 
1079 /*
1080  * Process interrupt from USB device (We got data from interrupt pipe)
1081  */
1082 
1083 static void
1084 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1085 {
1086 	ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1087 	NG_NODE_UNREF((node_p) p);
1088 } /* ubt_intr_complete */
1089 
1090 static void
1091 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1092 {
1093 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1094 	usbd_xfer_handle	 h = (usbd_xfer_handle) arg1;
1095 	usbd_status		 s = (usbd_status) arg2;
1096 	struct mbuf		*m = NULL;
1097 	ng_hci_event_pkt_t	*hdr = NULL;
1098 	int			 error;
1099 
1100 	if (sc == NULL)
1101 		return;
1102 
1103 	KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1104 "%s: %s - No interrupt request is pending\n",
1105 		__func__, device_get_nameunit(sc->sc_dev)));
1106 
1107 	sc->sc_flags &= ~UBT_EVT_RECV;
1108 
1109 	m = sc->sc_intr_buffer;
1110 	sc->sc_intr_buffer = NULL;
1111 
1112 	hdr = mtod(m, ng_hci_event_pkt_t *);
1113 
1114 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1115 		NG_UBT_INFO(
1116 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1117 
1118 		NG_FREE_M(m);
1119 		return;
1120 	}
1121 
1122 	if (s == USBD_CANCELLED) {
1123 		NG_UBT_INFO(
1124 "%s: %s - Interrupt xfer cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
1125 
1126 		NG_FREE_M(m);
1127 		return;
1128 	}
1129 
1130 	if (s != USBD_NORMAL_COMPLETION) {
1131 		NG_UBT_WARN(
1132 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1133 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1134 
1135 		if (s == USBD_STALLED)
1136 			usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1137 
1138 		NG_UBT_STAT_IERROR(sc->sc_stat);
1139 		NG_FREE_M(m);
1140 
1141 		return; /* XXX FIXME we should restart after some delay */
1142 	}
1143 
1144 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1145 	m->m_pkthdr.len += h->actlen;
1146 	m->m_len += h->actlen;
1147 
1148 	NG_UBT_INFO(
1149 "%s: %s - Got %d bytes from interrupt pipe\n",
1150 		__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1151 
1152 	if (m->m_pkthdr.len < sizeof(*hdr)) {
1153 		NG_FREE_M(m);
1154 		goto done;
1155 	}
1156 
1157 	if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1158 		NG_UBT_INFO(
1159 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1160 			__func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len,
1161 			hdr->length);
1162 
1163 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1164 
1165 		NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1166 		if (error != 0)
1167 			NG_UBT_STAT_IERROR(sc->sc_stat);
1168 	} else {
1169 		NG_UBT_ERR(
1170 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1171 			__func__, device_get_nameunit(sc->sc_dev), hdr->length,
1172 			m->m_pkthdr.len);
1173 
1174 		NG_UBT_STAT_IERROR(sc->sc_stat);
1175 		NG_FREE_M(m);
1176 	}
1177 done:
1178 	ubt_intr_start(sc);
1179 } /* ubt_intr_complete2 */
1180 
1181 /*
1182  * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1183  */
1184 
1185 static usbd_status
1186 ubt_bulk_in_start(ubt_softc_p sc)
1187 {
1188 	struct mbuf	*m = NULL;
1189 	usbd_status	 status;
1190 
1191 	KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1192 "%s: %s - Another bulk-in request is pending\n",
1193 		__func__, device_get_nameunit(sc->sc_dev)));
1194 
1195 	/* Allocate new mbuf cluster */
1196 	MGETHDR(m, MB_DONTWAIT, MT_DATA);
1197 	if (m == NULL)
1198 		return (USBD_NOMEM);
1199 
1200 	MCLGET(m, MB_DONTWAIT);
1201 	if (!(m->m_flags & M_EXT)) {
1202 		NG_FREE_M(m);
1203 		return (USBD_NOMEM);
1204 	}
1205 
1206 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1207 		*mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1208 		m->m_pkthdr.len = m->m_len = 1;
1209 	} else
1210 		m->m_pkthdr.len = m->m_len = 0;
1211 
1212 	/* Initialize a bulk-in USB transfer and then schedule it */
1213 	usbd_setup_xfer(
1214 			sc->sc_bulk_in_xfer,
1215 			sc->sc_bulk_in_pipe,
1216 			(usbd_private_handle) sc->sc_node,
1217 			(void *)(mtod(m, u_int8_t *) + m->m_len),
1218 			MCLBYTES - m->m_len,
1219 			USBD_SHORT_XFER_OK,
1220 			USBD_NO_TIMEOUT,
1221 			ubt_bulk_in_complete);
1222 
1223 	NG_NODE_REF(sc->sc_node);
1224 
1225 	status = usbd_transfer(sc->sc_bulk_in_xfer);
1226 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1227 		NG_UBT_ERR(
1228 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1229 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1230 			status);
1231 
1232 		NG_NODE_UNREF(sc->sc_node);
1233 
1234 		NG_FREE_M(m);
1235 
1236 		return (status);
1237 	}
1238 
1239 	sc->sc_flags |= UBT_ACL_RECV;
1240 	sc->sc_bulk_in_buffer = m;
1241 
1242 	return (USBD_NORMAL_COMPLETION);
1243 } /* ubt_bulk_in_start */
1244 
1245 /*
1246  * USB bulk-in transfer callback
1247  */
1248 
1249 static void
1250 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1251 {
1252 	ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1253 	NG_NODE_UNREF((node_p) p);
1254 } /* ubt_bulk_in_complete */
1255 
1256 static void
1257 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1258 {
1259 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1260 	usbd_xfer_handle	 h = (usbd_xfer_handle) arg1;
1261 	usbd_status		 s = (usbd_status) arg2;
1262 	struct mbuf		*m = NULL;
1263 	ng_hci_acldata_pkt_t	*hdr = NULL;
1264 	int			 len;
1265 
1266 	if (sc == NULL)
1267 		return;
1268 
1269 	KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1270 "%s: %s - No bulk-in request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1271 
1272 	sc->sc_flags &= ~UBT_ACL_RECV;
1273 
1274 	m = sc->sc_bulk_in_buffer;
1275 	sc->sc_bulk_in_buffer = NULL;
1276 
1277 	hdr = mtod(m, ng_hci_acldata_pkt_t *);
1278 
1279 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1280 		NG_UBT_INFO(
1281 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1282 
1283 		NG_FREE_M(m);
1284 		return;
1285 	}
1286 
1287 	if (s == USBD_CANCELLED) {
1288 		NG_UBT_INFO(
1289 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1290 			__func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_in_pipe);
1291 
1292 		NG_FREE_M(m);
1293 		return;
1294 	}
1295 
1296 	if (s != USBD_NORMAL_COMPLETION) {
1297 		NG_UBT_WARN(
1298 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1299 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1300 
1301 		if (s == USBD_STALLED)
1302 			usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1303 
1304 		NG_UBT_STAT_IERROR(sc->sc_stat);
1305 		NG_FREE_M(m);
1306 
1307 		return; /* XXX FIXME we should restart after some delay */
1308 	}
1309 
1310 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1311 	m->m_pkthdr.len += h->actlen;
1312 	m->m_len += h->actlen;
1313 
1314 	NG_UBT_INFO(
1315 "%s: %s - Got %d bytes from bulk-in pipe\n",
1316 		__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1317 
1318 	if (m->m_pkthdr.len < sizeof(*hdr)) {
1319 		NG_FREE_M(m);
1320 		goto done;
1321 	}
1322 
1323 	len = le16toh(hdr->length);
1324 	if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1325 		NG_UBT_INFO(
1326 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1327 			__func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len, len);
1328 
1329 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1330 
1331 		NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1332 		if (len != 0)
1333 			NG_UBT_STAT_IERROR(sc->sc_stat);
1334 	} else {
1335 		NG_UBT_ERR(
1336 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1337 			__func__, device_get_nameunit(sc->sc_dev), len,
1338 			m->m_pkthdr.len);
1339 
1340 		NG_UBT_STAT_IERROR(sc->sc_stat);
1341 		NG_FREE_M(m);
1342 	}
1343 done:
1344 	ubt_bulk_in_start(sc);
1345 } /* ubt_bulk_in_complete2 */
1346 
1347 /*
1348  * Start bulk-out USB transfer. Must be called with node locked
1349  */
1350 
1351 static usbd_status
1352 ubt_bulk_out_start(ubt_softc_p sc)
1353 {
1354 	struct mbuf	*m = NULL;
1355 	usbd_status	status;
1356 
1357 	KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1358 "%s: %s - Another bulk-out request is pending\n",
1359 		__func__, device_get_nameunit(sc->sc_dev)));
1360 
1361 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1362 	if (m == NULL) {
1363 		NG_UBT_INFO(
1364 "%s: %s - ACL data queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
1365 
1366  		return (USBD_NORMAL_COMPLETION);
1367 	}
1368 
1369 	/*
1370 	 * Check ACL data frame size and copy it back to linear USB
1371 	 * transfer buffer.
1372 	 */
1373 
1374 	if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1375 		panic(
1376 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1377 			__func__, device_get_nameunit(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1378 			m->m_pkthdr.len);
1379 
1380 	m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1381 
1382 	/* Initialize a bulk-out USB transfer and then schedule it */
1383 	usbd_setup_xfer(
1384 			sc->sc_bulk_out_xfer,
1385 			sc->sc_bulk_out_pipe,
1386 			(usbd_private_handle) sc->sc_node,
1387 			sc->sc_bulk_out_buffer,
1388 			m->m_pkthdr.len,
1389 			USBD_NO_COPY,
1390 			USBD_DEFAULT_TIMEOUT, /* XXX */
1391 			ubt_bulk_out_complete);
1392 
1393 	NG_NODE_REF(sc->sc_node);
1394 
1395 	status = usbd_transfer(sc->sc_bulk_out_xfer);
1396 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1397 		NG_UBT_ERR(
1398 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1399 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1400 			status);
1401 
1402 		NG_NODE_UNREF(sc->sc_node);
1403 
1404 		NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1405 		NG_UBT_STAT_OERROR(sc->sc_stat);
1406 
1407 		/* XXX FIXME should we try to start another transfer? */
1408 	} else {
1409 		NG_UBT_INFO(
1410 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1411 			__func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len);
1412 
1413 		sc->sc_flags |= UBT_ACL_XMIT;
1414 		status = USBD_NORMAL_COMPLETION;
1415 	}
1416 
1417 	NG_FREE_M(m);
1418 
1419 	return (status);
1420 } /* ubt_bulk_out_start */
1421 
1422 /*
1423  * USB bulk-out transfer callback
1424  */
1425 
1426 static void
1427 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1428 {
1429 	ng_send_fn((node_p) p,  NULL, ubt_bulk_out_complete2, (void *) h, s);
1430 	NG_NODE_UNREF((node_p) p);
1431 } /* ubt_bulk_out_complete */
1432 
1433 static void
1434 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1435 {
1436 	ubt_softc_p		sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1437 	usbd_xfer_handle	h = (usbd_xfer_handle) arg1;
1438 	usbd_status		s = (usbd_status) arg2;
1439 
1440 	if (sc == NULL)
1441 		return;
1442 
1443 	KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1444 "%s: %s - No bulk-out request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1445 
1446 	sc->sc_flags &= ~UBT_ACL_XMIT;
1447 
1448 	if (s == USBD_CANCELLED) {
1449 		NG_UBT_INFO(
1450 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1451 			__func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_out_pipe);
1452 
1453 		return;
1454 	}
1455 
1456 	if (s != USBD_NORMAL_COMPLETION) {
1457 		NG_UBT_WARN(
1458 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1459 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1460 
1461 		if (s == USBD_STALLED)
1462 			usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1463 
1464 		NG_UBT_STAT_OERROR(sc->sc_stat);
1465 	} else {
1466 		NG_UBT_INFO(
1467 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1468 			__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1469 
1470 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1471 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1472 	}
1473 
1474 	if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1475 		ubt_bulk_out_start(sc);
1476 } /* ubt_bulk_out_complete2 */
1477 
1478 /*
1479  * Start Isochronous-in USB transfer. Must be called with node locked
1480  */
1481 
1482 static usbd_status
1483 ubt_isoc_in_start(ubt_softc_p sc)
1484 {
1485 	usbd_status	status;
1486 	int		i;
1487 
1488 	KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1489 "%s: %s - Another isoc-in request is pending\n",
1490                 __func__, device_get_nameunit(sc->sc_dev)));
1491 
1492 	/* Initialize a isoc-in USB transfer and then schedule it */
1493 	for (i = 0; i < sc->sc_isoc_nframes; i++)
1494 		sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1495 
1496 	usbd_setup_isoc_xfer(
1497 			sc->sc_isoc_in_xfer,
1498 			sc->sc_isoc_in_pipe,
1499 			(usbd_private_handle) sc->sc_node,
1500 			sc->sc_isoc_in_frlen,
1501 			sc->sc_isoc_nframes,
1502 			USBD_NO_COPY, /* XXX flags */
1503 			ubt_isoc_in_complete);
1504 
1505 	NG_NODE_REF(sc->sc_node);
1506 
1507 	status = usbd_transfer(sc->sc_isoc_in_xfer);
1508 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1509 		NG_UBT_ERR(
1510 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1511 			__func__, device_get_nameunit(sc->sc_dev),
1512 			usbd_errstr(status), status);
1513 
1514 		NG_NODE_UNREF(sc->sc_node);
1515 
1516 		return (status);
1517 	}
1518 
1519 	sc->sc_flags |= UBT_SCO_RECV;
1520 
1521 	return (USBD_NORMAL_COMPLETION);
1522 } /* ubt_isoc_in_start */
1523 
1524 /*
1525  * USB isochronous transfer callback
1526  */
1527 
1528 static void
1529 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1530 {
1531 	ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1532 	NG_NODE_UNREF((node_p) p);
1533 } /* ubt_isoc_in_complete */
1534 
1535 static void
1536 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1537 {
1538 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1539 	usbd_xfer_handle	 h = (usbd_xfer_handle) arg1;
1540 	usbd_status		 s = (usbd_status) arg2;
1541 	struct mbuf		*m = NULL;
1542 	ng_hci_scodata_pkt_t	*hdr = NULL;
1543 	u_int8_t		*b = NULL;
1544 	int			 i;
1545 
1546 	if (sc == NULL)
1547 		return;
1548 
1549 	KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1550 "%s: %s - No isoc-in request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1551 
1552 	sc->sc_flags &= ~UBT_SCO_RECV;
1553 
1554 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1555 		NG_UBT_INFO(
1556 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1557 
1558 		return;
1559 	}
1560 
1561 	if (s == USBD_CANCELLED) {
1562 		NG_UBT_INFO(
1563 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1564 			__func__, device_get_nameunit(sc->sc_dev), sc->sc_isoc_in_pipe);
1565 
1566 		return;
1567 	}
1568 
1569 	if (s != USBD_NORMAL_COMPLETION) {
1570 		NG_UBT_WARN(
1571 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1572 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1573 
1574 		if (s == USBD_STALLED)
1575 			usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1576 
1577 		NG_UBT_STAT_IERROR(sc->sc_stat);
1578 
1579 		return; /* XXX FIXME we should restart after some delay */
1580 	}
1581 
1582 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1583 
1584 	NG_UBT_INFO(
1585 "%s: %s - Got %d bytes from isoc-in pipe\n",
1586 		__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1587 
1588 	/* Copy SCO data frame to mbuf */
1589 	MGETHDR(m, MB_DONTWAIT, MT_DATA);
1590 	if (m == NULL) {
1591 		NG_UBT_ALERT(
1592 "%s: %s - Could not allocate mbuf\n",
1593 			__func__, device_get_nameunit(sc->sc_dev));
1594 
1595 		NG_UBT_STAT_IERROR(sc->sc_stat);
1596 		goto done;
1597 	}
1598 
1599 	/* Fix SCO data frame header if required */
1600 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1601 		*mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1602 		m->m_pkthdr.len = 1;
1603 		m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1604 	} else {
1605 		m->m_pkthdr.len = 0;
1606 		m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1607 	}
1608 
1609 	/*
1610 	 * XXX FIXME how do we know how many frames we have received?
1611 	 * XXX use frlen for now. is that correct?
1612 	 */
1613 
1614 	b = (u_int8_t *) sc->sc_isoc_in_buffer;
1615 
1616 	for (i = 0; i < sc->sc_isoc_nframes; i++) {
1617 		b += (i * sc->sc_isoc_size);
1618 
1619 		if (sc->sc_isoc_in_frlen[i] > 0)
1620 			m_copyback(m, m->m_pkthdr.len,
1621 				sc->sc_isoc_in_frlen[i], b);
1622 	}
1623 
1624 	if (m->m_pkthdr.len < sizeof(*hdr))
1625 		goto done;
1626 
1627 	hdr = mtod(m, ng_hci_scodata_pkt_t *);
1628 
1629 	if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1630 		NG_UBT_INFO(
1631 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1632 			__func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len,
1633 			hdr->length);
1634 
1635 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1636 
1637 		NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1638 		if (i != 0)
1639 			NG_UBT_STAT_IERROR(sc->sc_stat);
1640 	} else {
1641 		NG_UBT_ERR(
1642 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1643 			__func__, device_get_nameunit(sc->sc_dev), hdr->length,
1644 			m->m_pkthdr.len);
1645 
1646 		NG_UBT_STAT_IERROR(sc->sc_stat);
1647 		NG_FREE_M(m);
1648 	}
1649 done:
1650 	ubt_isoc_in_start(sc);
1651 } /* ubt_isoc_in_complete2 */
1652 
1653 /*
1654  * Start isochronous-out USB transfer. Must be called with node locked
1655  */
1656 
1657 static usbd_status
1658 ubt_isoc_out_start(ubt_softc_p sc)
1659 {
1660 	struct mbuf	*m = NULL;
1661 	u_int8_t	*b = NULL;
1662 	int		 i, len, nframes;
1663 	usbd_status	 status;
1664 
1665 	KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1666 "%s: %s - Another isoc-out request is pending\n",
1667 		__func__, device_get_nameunit(sc->sc_dev)));
1668 
1669 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1670 	if (m == NULL) {
1671 		NG_UBT_INFO(
1672 "%s: %s - SCO data queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
1673 
1674  		return (USBD_NORMAL_COMPLETION);
1675 	}
1676 
1677 	/* Copy entire SCO frame into USB transfer buffer and start transfer */
1678 	b = (u_int8_t *) sc->sc_isoc_out_buffer;
1679 	nframes = 0;
1680 
1681 	for (i = 0; i < sc->sc_isoc_nframes; i++) {
1682 		b += (i * sc->sc_isoc_size);
1683 
1684 		len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1685 		if (len > 0) {
1686 			m_copydata(m, 0, len, b);
1687 			m_adj(m, len);
1688 			nframes ++;
1689 		}
1690 
1691 		sc->sc_isoc_out_frlen[i] = len;
1692 	}
1693 
1694 	if (m->m_pkthdr.len > 0)
1695 		panic(
1696 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1697 			__func__, device_get_nameunit(sc->sc_dev), sc->sc_isoc_nframes,
1698 			sc->sc_isoc_size, m->m_pkthdr.len);
1699 
1700 	NG_FREE_M(m);
1701 
1702 	/* Initialize a isoc-out USB transfer and then schedule it */
1703 	usbd_setup_isoc_xfer(
1704 			sc->sc_isoc_out_xfer,
1705 			sc->sc_isoc_out_pipe,
1706 			(usbd_private_handle) sc->sc_node,
1707 			sc->sc_isoc_out_frlen,
1708 			nframes,
1709 			USBD_NO_COPY,
1710 			ubt_isoc_out_complete);
1711 
1712 	NG_NODE_REF(sc->sc_node);
1713 
1714 	status = usbd_transfer(sc->sc_isoc_out_xfer);
1715 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1716 		NG_UBT_ERR(
1717 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1718 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1719 			status);
1720 
1721 		NG_NODE_UNREF(sc->sc_node);
1722 
1723 		NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1724 		NG_UBT_STAT_OERROR(sc->sc_stat);
1725 	} else {
1726 		NG_UBT_INFO(
1727 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1728 			__func__, device_get_nameunit(sc->sc_dev), nframes,
1729 			sc->sc_isoc_size);
1730 
1731 		sc->sc_flags |= UBT_SCO_XMIT;
1732 		status = USBD_NORMAL_COMPLETION;
1733 	}
1734 
1735 	return (status);
1736 } /* ubt_isoc_out_start */
1737 
1738 /*
1739  * USB isoc-out. transfer callback
1740  */
1741 
1742 static void
1743 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1744 {
1745 	ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1746 	NG_NODE_UNREF((node_p) p);
1747 } /* ubt_isoc_out_complete */
1748 
1749 static void
1750 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1751 {
1752 	ubt_softc_p		sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1753 	usbd_xfer_handle	h = (usbd_xfer_handle) arg1;
1754 	usbd_status		s = (usbd_status) arg2;
1755 
1756 	if (sc == NULL)
1757 		return;
1758 
1759 	KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1760 "%s: %s - No isoc-out request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1761 
1762 	sc->sc_flags &= ~UBT_SCO_XMIT;
1763 
1764 	if (s == USBD_CANCELLED) {
1765 		NG_UBT_INFO(
1766 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1767 			__func__, device_get_nameunit(sc->sc_dev),
1768 			sc->sc_isoc_out_pipe);
1769 
1770 		return;
1771 	}
1772 
1773 	if (s != USBD_NORMAL_COMPLETION) {
1774 		NG_UBT_WARN(
1775 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1776 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1777 
1778 		if (s == USBD_STALLED)
1779 			usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1780 
1781 		NG_UBT_STAT_OERROR(sc->sc_stat);
1782 	} else {
1783 		NG_UBT_INFO(
1784 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1785 			__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1786 
1787 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1788 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1789 	}
1790 
1791 	if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1792 		ubt_isoc_out_start(sc);
1793 } /* ubt_isoc_out_complete2 */
1794 
1795 /*
1796  * Abort transfers on all USB pipes
1797  */
1798 
1799 static void
1800 ubt_reset(ubt_softc_p sc)
1801 {
1802 	/* Interrupt */
1803 	if (sc->sc_intr_pipe != NULL)
1804 		usbd_abort_pipe(sc->sc_intr_pipe);
1805 
1806 	/* Bulk-in/out */
1807 	if (sc->sc_bulk_in_pipe != NULL)
1808 		usbd_abort_pipe(sc->sc_bulk_in_pipe);
1809 	if (sc->sc_bulk_out_pipe != NULL)
1810 		usbd_abort_pipe(sc->sc_bulk_out_pipe);
1811 
1812 	/* Isoc-in/out */
1813 	if (sc->sc_isoc_in_pipe != NULL)
1814 		usbd_abort_pipe(sc->sc_isoc_in_pipe);
1815 	if (sc->sc_isoc_out_pipe != NULL)
1816 		usbd_abort_pipe(sc->sc_isoc_out_pipe);
1817 
1818 	/* Cleanup queues */
1819 	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1820 	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1821 	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1822 } /* ubt_reset */
1823 
1824 /****************************************************************************
1825  ****************************************************************************
1826  **                        Netgraph specific
1827  ****************************************************************************
1828  ****************************************************************************/
1829 
1830 /*
1831  * Netgraph node constructor. Do not allow to create node of this type.
1832  */
1833 
1834 static int
1835 ng_ubt_constructor(node_p node)
1836 {
1837 	return (EINVAL);
1838 } /* ng_ubt_constructor */
1839 
1840 /*
1841  * Netgraph node destructor. Destroy node only when device has been detached
1842  */
1843 
1844 static int
1845 ng_ubt_shutdown(node_p node)
1846 {
1847 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1848 
1849 	/* Let old node go */
1850 	NG_NODE_SET_PRIVATE(node, NULL);
1851 	NG_NODE_UNREF(node);
1852 
1853 	if (sc == NULL)
1854 		goto done;
1855 
1856 	/* Create Netgraph node */
1857 	if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1858 		printf("%s: Could not create Netgraph node\n",
1859 			device_get_nameunit(sc->sc_dev));
1860 		sc->sc_node = NULL;
1861 		goto done;
1862 	}
1863 
1864 	/* Name node */
1865 	if (ng_name_node(sc->sc_node, device_get_nameunit(sc->sc_dev)) != 0) {
1866 		printf("%s: Could not name Netgraph node\n",
1867 			device_get_nameunit(sc->sc_dev));
1868 		NG_NODE_UNREF(sc->sc_node);
1869 		sc->sc_node = NULL;
1870 		goto done;
1871 	}
1872 
1873 	NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1874 	NG_NODE_FORCE_WRITER(sc->sc_node);
1875 done:
1876 	return (0);
1877 } /* ng_ubt_shutdown */
1878 
1879 /*
1880  * Create new hook. There can only be one.
1881  */
1882 
1883 static int
1884 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1885 {
1886 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1887 
1888 	if (strcmp(name, NG_UBT_HOOK) != 0)
1889 		return (EINVAL);
1890 
1891 	if (sc->sc_hook != NULL)
1892 		return (EISCONN);
1893 
1894 	sc->sc_hook = hook;
1895 
1896 	return (0);
1897 } /* ng_ubt_newhook */
1898 
1899 /*
1900  * Connect hook. Start incoming USB transfers
1901  */
1902 
1903 static int
1904 ng_ubt_connect(hook_p hook)
1905 {
1906 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1907 	usbd_status	status;
1908 
1909 	NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1910 
1911 	/* Start intr transfer */
1912 	status = ubt_intr_start(sc);
1913 	if (status != USBD_NORMAL_COMPLETION) {
1914 		NG_UBT_ALERT(
1915 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
1916 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1917 			status);
1918 		goto fail;
1919 	}
1920 
1921 	/* Start bulk-in transfer */
1922 	status = ubt_bulk_in_start(sc);
1923 	if (status != USBD_NORMAL_COMPLETION) {
1924 		NG_UBT_ALERT(
1925 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
1926 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1927 			status);
1928 		goto fail;
1929 	}
1930 
1931 #if 0 /* XXX FIXME */
1932 	/* Start isoc-in transfer */
1933 	status = ubt_isoc_in_start(sc);
1934 	if (status != USBD_NORMAL_COMPLETION) {
1935 		NG_UBT_ALERT(
1936 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
1937 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1938 			status);
1939 		goto fail;
1940 	}
1941 #endif
1942 
1943 	return (0);
1944 fail:
1945 	ubt_reset(sc);
1946 	sc->sc_hook = NULL;
1947 
1948 	return (ENXIO);
1949 } /* ng_ubt_connect */
1950 
1951 /*
1952  * Disconnect hook
1953  */
1954 
1955 static int
1956 ng_ubt_disconnect(hook_p hook)
1957 {
1958 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1959 
1960 	if (sc != NULL) {
1961 		if (hook != sc->sc_hook)
1962 			return (EINVAL);
1963 
1964 		ubt_reset(sc);
1965 		sc->sc_hook = NULL;
1966 	}
1967 
1968 	return (0);
1969 } /* ng_ubt_disconnect */
1970 
1971 /*
1972  * Process control message
1973  */
1974 
1975 static int
1976 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
1977 {
1978 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1979 	struct ng_mesg		*msg = NULL, *rsp = NULL;
1980 	struct ng_bt_mbufq	*q = NULL;
1981 	int			 error = 0, queue, qlen;
1982 
1983 	if (sc == NULL) {
1984 		NG_FREE_ITEM(item);
1985 		return (EHOSTDOWN);
1986 	}
1987 
1988 	NGI_GET_MSG(item, msg);
1989 
1990 	switch (msg->header.typecookie) {
1991 	case NGM_GENERIC_COOKIE:
1992 		switch (msg->header.cmd) {
1993 		case NGM_TEXT_STATUS:
1994 			NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_WAITOK | M_NULLOK);
1995 			if (rsp == NULL)
1996 				error = ENOMEM;
1997 			else
1998 				snprintf(rsp->data, NG_TEXTRESPONSE,
1999 					"Hook: %s\n"   \
2000 					"Flags: %#x\n" \
2001 					"Debug: %d\n"  \
2002 					"CMD queue: [have:%d,max:%d]\n" \
2003 					"ACL queue: [have:%d,max:%d]\n" \
2004 					"SCO queue: [have:%d,max:%d]",
2005 					(sc->sc_hook != NULL)? NG_UBT_HOOK : "",
2006 					sc->sc_flags,
2007 					sc->sc_debug,
2008 					NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
2009 					sc->sc_cmdq.maxlen,
2010 					NG_BT_MBUFQ_LEN(&sc->sc_aclq),
2011 					sc->sc_aclq.maxlen,
2012 					NG_BT_MBUFQ_LEN(&sc->sc_scoq),
2013 					sc->sc_scoq.maxlen);
2014 			break;
2015 
2016 		default:
2017 			error = EINVAL;
2018 			break;
2019 		}
2020 		break;
2021 
2022 	case NGM_UBT_COOKIE:
2023 		switch (msg->header.cmd) {
2024 		case NGM_UBT_NODE_SET_DEBUG:
2025 			if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2026 				error = EMSGSIZE;
2027 			else
2028 				sc->sc_debug =
2029 					*((ng_ubt_node_debug_ep *)(msg->data));
2030 			break;
2031 
2032 		case NGM_UBT_NODE_GET_DEBUG:
2033 			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2034 				M_WAITOK | M_NULLOK);
2035 			if (rsp == NULL)
2036 				error = ENOMEM;
2037 			else
2038 				*((ng_ubt_node_debug_ep *)(rsp->data)) =
2039 					sc->sc_debug;
2040                         break;
2041 
2042 		case NGM_UBT_NODE_SET_QLEN:
2043 			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2044 				error = EMSGSIZE;
2045 			else {
2046 				queue = ((ng_ubt_node_qlen_ep *)
2047 						(msg->data))->queue;
2048 				qlen = ((ng_ubt_node_qlen_ep *)
2049 						(msg->data))->qlen;
2050 
2051 				if (qlen <= 0) {
2052 					error = EINVAL;
2053 					break;
2054 				}
2055 
2056 				switch (queue) {
2057 				case NGM_UBT_NODE_QUEUE_CMD:
2058 					q = &sc->sc_cmdq;
2059 					break;
2060 
2061 				case NGM_UBT_NODE_QUEUE_ACL:
2062 					q = &sc->sc_aclq;
2063 					break;
2064 
2065 				case NGM_UBT_NODE_QUEUE_SCO:
2066 					q = &sc->sc_scoq;
2067 					break;
2068 
2069 				default:
2070 					q = NULL;
2071 					error = EINVAL;
2072 					break;
2073 				}
2074 
2075 				if (q != NULL)
2076 					q->maxlen = qlen;
2077 			}
2078 			break;
2079 
2080 		case NGM_UBT_NODE_GET_QLEN:
2081 			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2082 				error = EMSGSIZE;
2083 				break;
2084 			}
2085 
2086 			queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2087 			switch (queue) {
2088 			case NGM_UBT_NODE_QUEUE_CMD:
2089 				q = &sc->sc_cmdq;
2090 				break;
2091 
2092 			case NGM_UBT_NODE_QUEUE_ACL:
2093 				q = &sc->sc_aclq;
2094 				break;
2095 
2096 			case NGM_UBT_NODE_QUEUE_SCO:
2097 				q = &sc->sc_scoq;
2098 				break;
2099 
2100 			default:
2101 				q = NULL;
2102 				error = EINVAL;
2103 				break;
2104 			}
2105 
2106 			if (q != NULL) {
2107 				NG_MKRESPONSE(rsp, msg,
2108 					sizeof(ng_ubt_node_qlen_ep), M_WAITOK | M_NULLOK);
2109 				if (rsp == NULL) {
2110 					error = ENOMEM;
2111 					break;
2112 				}
2113 
2114 				((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2115 					queue;
2116 				((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2117 					q->maxlen;
2118 			}
2119 			break;
2120 
2121 		case NGM_UBT_NODE_GET_STAT:
2122 			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2123 				M_WAITOK | M_NULLOK);
2124 			if (rsp == NULL)
2125 				error = ENOMEM;
2126 			else
2127 				bcopy(&sc->sc_stat, rsp->data,
2128 					sizeof(ng_ubt_node_stat_ep));
2129 			break;
2130 
2131 		case NGM_UBT_NODE_RESET_STAT:
2132 			NG_UBT_STAT_RESET(sc->sc_stat);
2133 			break;
2134 
2135 		default:
2136 			error = EINVAL;
2137 			break;
2138 		}
2139 		break;
2140 
2141 	default:
2142 		error = EINVAL;
2143 		break;
2144 	}
2145 
2146 	NG_RESPOND_MSG(error, node, item, rsp);
2147 	NG_FREE_MSG(msg);
2148 
2149 	return (error);
2150 } /* ng_ubt_rcvmsg */
2151 
2152 /*
2153  * Process data
2154  */
2155 
2156 static int
2157 ng_ubt_rcvdata(hook_p hook, item_p item)
2158 {
2159 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2160 	struct mbuf		*m = NULL;
2161 	usbd_status		(*f)(ubt_softc_p) = NULL;
2162 	struct ng_bt_mbufq	*q = NULL;
2163 	int			 b, error = 0;
2164 
2165 	if (sc == NULL) {
2166 		error = EHOSTDOWN;
2167 		goto done;
2168 	}
2169 
2170 	if (hook != sc->sc_hook) {
2171 		error = EINVAL;
2172 		goto done;
2173 	}
2174 
2175 	/* Deatch mbuf and get HCI frame type */
2176 	NGI_GET_M(item, m);
2177 
2178 	/* Process HCI frame */
2179 	switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
2180 	case NG_HCI_CMD_PKT:
2181 		f = ubt_request_start;
2182 		q = &sc->sc_cmdq;
2183 		b = UBT_CMD_XMIT;
2184 		break;
2185 
2186 	case NG_HCI_ACL_DATA_PKT:
2187 		f = ubt_bulk_out_start;
2188 		q = &sc->sc_aclq;
2189 		b = UBT_ACL_XMIT;
2190 		break;
2191 
2192 #if 0 /* XXX FIXME */
2193 	case NG_HCI_SCO_DATA_PKT:
2194 		f = ubt_isoc_out_start;
2195 		q = &sc->sc_scoq;
2196 		b = UBT_SCO_XMIT;
2197 		break;
2198 #endif
2199 
2200 	default:
2201 		NG_UBT_ERR(
2202 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2203 			__func__, device_get_nameunit(sc->sc_dev), *mtod(m, u_int8_t *),
2204 			m->m_pkthdr.len);
2205 
2206 		NG_FREE_M(m);
2207 		error = EINVAL;
2208 
2209 		goto done;
2210 		/* NOT REACHED */
2211 	}
2212 
2213 	/* Loose frame type, if required */
2214 	if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2215 		m_adj(m, sizeof(u_int8_t));
2216 
2217 	if (NG_BT_MBUFQ_FULL(q)) {
2218 		NG_UBT_ERR(
2219 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2220 			__func__, device_get_nameunit(sc->sc_dev),
2221 			*mtod(m, u_int8_t *), m->m_pkthdr.len);
2222 
2223 		NG_FREE_M(m);
2224 	} else
2225 		NG_BT_MBUFQ_ENQUEUE(q, m);
2226 
2227 	if (!(sc->sc_flags & b))
2228 		if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2229 			error = EIO;
2230 done:
2231 	NG_FREE_ITEM(item);
2232 
2233 	return (error);
2234 } /* ng_ubt_rcvdata */
2235 
2236