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