xref: /freebsd/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c (revision b3aaa0cc21c63d388230c7ef2a80abd631ff20d5)
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_abort_pipe(sc->sc_intr_pipe);
816 		usbd_close_pipe(sc->sc_intr_pipe);
817 		sc->sc_intr_pipe = NULL;
818 	}
819 
820 	if (sc->sc_bulk_in_pipe != NULL) {
821 		usbd_abort_pipe(sc->sc_bulk_in_pipe);
822 		usbd_close_pipe(sc->sc_bulk_in_pipe);
823 		sc->sc_bulk_in_pipe = NULL;
824 	}
825 	if (sc->sc_bulk_out_pipe != NULL) {
826 		usbd_abort_pipe(sc->sc_bulk_out_pipe);
827 		usbd_close_pipe(sc->sc_bulk_out_pipe);
828 		sc->sc_bulk_out_pipe = NULL;
829 	}
830 
831 	if (sc->sc_isoc_in_pipe != NULL) {
832 		usbd_abort_pipe(sc->sc_isoc_in_pipe);
833 		usbd_close_pipe(sc->sc_isoc_in_pipe);
834 		sc->sc_isoc_in_pipe = NULL;
835 	}
836 	if (sc->sc_isoc_out_pipe != NULL) {
837 		usbd_abort_pipe(sc->sc_isoc_out_pipe);
838 		usbd_close_pipe(sc->sc_isoc_out_pipe);
839 		sc->sc_isoc_out_pipe = NULL;
840 	}
841 
842 	/* Destroy USB transfer handles */
843 	if (sc->sc_ctrl_xfer != NULL) {
844 		usbd_free_xfer(sc->sc_ctrl_xfer);
845 		sc->sc_ctrl_xfer = NULL;
846 	}
847 
848 	if (sc->sc_intr_xfer != NULL) {
849 		usbd_free_xfer(sc->sc_intr_xfer);
850 		sc->sc_intr_xfer = NULL;
851 	}
852 
853 	if (sc->sc_bulk_in_xfer != NULL) {
854 		usbd_free_xfer(sc->sc_bulk_in_xfer);
855 		sc->sc_bulk_in_xfer = NULL;
856 	}
857 	if (sc->sc_bulk_out_xfer != NULL) {
858 		usbd_free_xfer(sc->sc_bulk_out_xfer);
859 		sc->sc_bulk_out_xfer = NULL;
860 	}
861 
862 	for (i = 0; i < NG_UBT_NXFERS; i++) {
863 		if (sc->sc_isoc_in[i].xfer != NULL) {
864 			usbd_free_xfer(sc->sc_isoc_in[i].xfer);
865 			sc->sc_isoc_in[i].xfer = NULL;
866 			sc->sc_isoc_in[i].buffer = NULL;
867 		}
868 
869 		if (sc->sc_isoc_in[i].frlen != NULL) {
870 			free(sc->sc_isoc_in[i].frlen, M_USBDEV);
871 			sc->sc_isoc_in[i].frlen = NULL;
872 		}
873 	}
874 
875 	for (i = 0; i < NG_UBT_NXFERS; i++) {
876 		if (sc->sc_isoc_out[i].xfer != NULL) {
877 			usbd_free_xfer(sc->sc_isoc_out[i].xfer);
878 			sc->sc_isoc_out[i].xfer = NULL;
879 			sc->sc_isoc_out[i].buffer = NULL;
880 		}
881 
882 		if (sc->sc_isoc_out[i].frlen != NULL) {
883 			free(sc->sc_isoc_out[i].frlen, M_USBDEV);
884 			sc->sc_isoc_out[i].frlen = NULL;
885 		}
886 	}
887 
888 	NG_FREE_M(sc->sc_bulk_in_buffer);
889 	NG_FREE_M(sc->sc_isoc_in_buffer);
890 
891 	/* Destroy queues */
892 	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
893 	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
894 	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
895 
896 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
897 
898 	return (0);
899 } /* ubt_detach */
900 
901 /*
902  * Start USB control request (HCI command). Must be called with node locked
903  */
904 
905 static usbd_status
906 ubt_request_start(ubt_softc_p sc)
907 {
908 	usb_device_request_t	 req;
909 	struct mbuf		*m = NULL;
910 	usbd_status		 status;
911 
912 	KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
913 "%s: %s - Another control request is pending\n",
914 		__func__, device_get_nameunit(sc->sc_dev)));
915 
916 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
917 	if (m == NULL) {
918 		NG_UBT_INFO(
919 "%s: %s - HCI command queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
920 
921 		return (USBD_NORMAL_COMPLETION);
922 	}
923 
924 	/*
925 	 * Check HCI command frame size and copy it back to
926 	 * linear USB transfer buffer.
927 	 */
928 
929 	if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
930 		panic(
931 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
932 			__func__, device_get_nameunit(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
933 			m->m_pkthdr.len);
934 
935 	m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
936 
937 	/* Initialize a USB control request and then schedule it */
938 	bzero(&req, sizeof(req));
939 	req.bmRequestType = UBT_HCI_REQUEST;
940 	USETW(req.wLength, m->m_pkthdr.len);
941 
942 	NG_UBT_INFO(
943 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
944 		__func__, device_get_nameunit(sc->sc_dev), req.bmRequestType,
945 		UGETW(req.wLength));
946 
947 	usbd_setup_default_xfer(
948 		sc->sc_ctrl_xfer,
949 		sc->sc_udev,
950 		(usbd_private_handle) sc->sc_node,
951 		USBD_DEFAULT_TIMEOUT, /* XXX */
952 		&req,
953 		sc->sc_ctrl_buffer,
954 		m->m_pkthdr.len,
955 		USBD_NO_COPY,
956 		ubt_request_complete);
957 
958 	NG_NODE_REF(sc->sc_node);
959 
960 	status = usbd_transfer(sc->sc_ctrl_xfer);
961 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
962 		NG_UBT_ERR(
963 "%s: %s - Could not start control request. %s (%d)\n",
964 			__func__, device_get_nameunit(sc->sc_dev),
965 			usbd_errstr(status), status);
966 
967 		NG_NODE_UNREF(sc->sc_node);
968 
969 		NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
970 		NG_UBT_STAT_OERROR(sc->sc_stat);
971 
972 		/* XXX FIXME should we try to resubmit another request? */
973 	} else {
974 		NG_UBT_INFO(
975 "%s: %s - Control request has been started\n",
976 			__func__, device_get_nameunit(sc->sc_dev));
977 
978 		sc->sc_flags |= UBT_CMD_XMIT;
979 		status = USBD_NORMAL_COMPLETION;
980 	}
981 
982 	NG_FREE_M(m);
983 
984 	return (status);
985 } /* ubt_request_start */
986 
987 /*
988  * USB control request callback
989  */
990 
991 static void
992 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
993 {
994 	ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
995 	NG_NODE_UNREF((node_p) p);
996 } /* ubt_request_complete */
997 
998 static void
999 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1000 {
1001 	ubt_softc_p		sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1002 	usbd_xfer_handle	h = (usbd_xfer_handle) arg1;
1003 	usbd_status		s = (usbd_status) arg2;
1004 
1005 	if (sc == NULL)
1006 		return;
1007 
1008 	KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
1009 "%s: %s - No control request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1010 
1011 	sc->sc_flags &= ~UBT_CMD_XMIT;
1012 
1013 	if (s == USBD_CANCELLED) {
1014 		NG_UBT_INFO(
1015 "%s: %s - Control request cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
1016 
1017 		return;
1018 	}
1019 
1020 	if (s != USBD_NORMAL_COMPLETION) {
1021 		NG_UBT_ERR(
1022 "%s: %s - Control request failed. %s (%d)\n",
1023 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1024 
1025 		if (s == USBD_STALLED)
1026 			usbd_clear_endpoint_stall_async(h->pipe);
1027 
1028 		NG_UBT_STAT_OERROR(sc->sc_stat);
1029 	} else {
1030 		NG_UBT_INFO(
1031 "%s: %s - Sent %d bytes to control pipe\n",
1032 			__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1033 
1034 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1035 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1036 	}
1037 
1038 	if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
1039 		ubt_request_start(sc);
1040 } /* ubt_request_complete2 */
1041 
1042 /*
1043  * Start interrupt transfer. Must be called when node is locked
1044  */
1045 
1046 static usbd_status
1047 ubt_intr_start(ubt_softc_p sc)
1048 {
1049 	struct mbuf	*m = NULL;
1050 	usbd_status	 status;
1051 
1052 	KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
1053 "%s: %s - Another interrupt request is pending\n",
1054 		__func__, device_get_nameunit(sc->sc_dev)));
1055 
1056 	/* Allocate new mbuf cluster */
1057 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1058 	if (m == NULL)
1059 		return (USBD_NOMEM);
1060 
1061 	MCLGET(m, M_DONTWAIT);
1062 	if (!(m->m_flags & M_EXT)) {
1063 		NG_FREE_M(m);
1064 		return (USBD_NOMEM);
1065 	}
1066 
1067 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1068 		*mtod(m, uint8_t *) = NG_HCI_EVENT_PKT;
1069 		m->m_pkthdr.len = m->m_len = 1;
1070 	} else
1071 		m->m_pkthdr.len = m->m_len = 0;
1072 
1073 	/* Initialize a USB transfer and then schedule it */
1074 	usbd_setup_xfer(
1075 			sc->sc_intr_xfer,
1076 			sc->sc_intr_pipe,
1077 			(usbd_private_handle) sc->sc_node,
1078 			(void *)(mtod(m, uint8_t *) + m->m_len),
1079 			MCLBYTES - m->m_len,
1080 			USBD_SHORT_XFER_OK,
1081 			USBD_NO_TIMEOUT,
1082 			ubt_intr_complete);
1083 
1084 	NG_NODE_REF(sc->sc_node);
1085 
1086 	status = usbd_transfer(sc->sc_intr_xfer);
1087 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1088 		NG_UBT_ERR(
1089 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1090 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1091 			status);
1092 
1093 		NG_NODE_UNREF(sc->sc_node);
1094 
1095 		NG_FREE_M(m);
1096 
1097 		return (status);
1098 	}
1099 
1100 	sc->sc_flags |= UBT_EVT_RECV;
1101 	sc->sc_intr_buffer = m;
1102 
1103 	return (USBD_NORMAL_COMPLETION);
1104 } /* ubt_intr_start */
1105 
1106 /*
1107  * Process interrupt from USB device (We got data from interrupt pipe)
1108  */
1109 
1110 static void
1111 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1112 {
1113 	ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1114 	NG_NODE_UNREF((node_p) p);
1115 } /* ubt_intr_complete */
1116 
1117 static void
1118 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1119 {
1120 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1121 	usbd_xfer_handle	 h = (usbd_xfer_handle) arg1;
1122 	usbd_status		 s = (usbd_status) arg2;
1123 	struct mbuf		*m = NULL;
1124 	ng_hci_event_pkt_t	*hdr = NULL;
1125 	int			 error;
1126 
1127 	if (sc == NULL)
1128 		return;
1129 
1130 	KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1131 "%s: %s - No interrupt request is pending\n",
1132 		__func__, device_get_nameunit(sc->sc_dev)));
1133 
1134 	sc->sc_flags &= ~UBT_EVT_RECV;
1135 
1136 	m = sc->sc_intr_buffer;
1137 	sc->sc_intr_buffer = NULL;
1138 
1139 	hdr = mtod(m, ng_hci_event_pkt_t *);
1140 
1141 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1142 		NG_UBT_INFO(
1143 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1144 
1145 		NG_FREE_M(m);
1146 		return;
1147 	}
1148 
1149 	if (s == USBD_CANCELLED) {
1150 		NG_UBT_INFO(
1151 "%s: %s - Interrupt xfer cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
1152 
1153 		NG_FREE_M(m);
1154 		return;
1155 	}
1156 
1157 	if (s != USBD_NORMAL_COMPLETION) {
1158 		NG_UBT_WARN(
1159 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1160 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1161 
1162 		if (s == USBD_STALLED)
1163 			usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1164 
1165 		NG_UBT_STAT_IERROR(sc->sc_stat);
1166 		NG_FREE_M(m);
1167 
1168 		return; /* XXX FIXME we should restart after some delay */
1169 	}
1170 
1171 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1172 	m->m_pkthdr.len += h->actlen;
1173 	m->m_len += h->actlen;
1174 
1175 	NG_UBT_INFO(
1176 "%s: %s - Got %d bytes from interrupt pipe\n",
1177 		__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1178 
1179 	if (m->m_pkthdr.len < sizeof(*hdr)) {
1180 		NG_FREE_M(m);
1181 		goto done;
1182 	}
1183 
1184 	if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1185 		NG_UBT_INFO(
1186 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1187 			__func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len,
1188 			hdr->length);
1189 
1190 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1191 
1192 		NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1193 		if (error != 0)
1194 			NG_UBT_STAT_IERROR(sc->sc_stat);
1195 	} else {
1196 		NG_UBT_ERR(
1197 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1198 			__func__, device_get_nameunit(sc->sc_dev), hdr->length,
1199 			m->m_pkthdr.len);
1200 
1201 		NG_UBT_STAT_IERROR(sc->sc_stat);
1202 		NG_FREE_M(m);
1203 	}
1204 done:
1205 	ubt_intr_start(sc);
1206 } /* ubt_intr_complete2 */
1207 
1208 /*
1209  * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1210  */
1211 
1212 static usbd_status
1213 ubt_bulk_in_start(ubt_softc_p sc)
1214 {
1215 	struct mbuf	*m = NULL;
1216 	usbd_status	 status;
1217 
1218 	KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1219 "%s: %s - Another bulk-in request is pending\n",
1220 		__func__, device_get_nameunit(sc->sc_dev)));
1221 
1222 	/* Allocate new mbuf cluster */
1223 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1224 	if (m == NULL)
1225 		return (USBD_NOMEM);
1226 
1227 	MCLGET(m, M_DONTWAIT);
1228 	if (!(m->m_flags & M_EXT)) {
1229 		NG_FREE_M(m);
1230 		return (USBD_NOMEM);
1231 	}
1232 
1233 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1234 		*mtod(m, uint8_t *) = NG_HCI_ACL_DATA_PKT;
1235 		m->m_pkthdr.len = m->m_len = 1;
1236 	} else
1237 		m->m_pkthdr.len = m->m_len = 0;
1238 
1239 	/* Initialize a bulk-in USB transfer and then schedule it */
1240 	usbd_setup_xfer(
1241 			sc->sc_bulk_in_xfer,
1242 			sc->sc_bulk_in_pipe,
1243 			(usbd_private_handle) sc->sc_node,
1244 			(void *)(mtod(m, uint8_t *) + m->m_len),
1245 			MCLBYTES - m->m_len,
1246 			USBD_SHORT_XFER_OK,
1247 			USBD_NO_TIMEOUT,
1248 			ubt_bulk_in_complete);
1249 
1250 	NG_NODE_REF(sc->sc_node);
1251 
1252 	status = usbd_transfer(sc->sc_bulk_in_xfer);
1253 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1254 		NG_UBT_ERR(
1255 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1256 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1257 			status);
1258 
1259 		NG_NODE_UNREF(sc->sc_node);
1260 
1261 		NG_FREE_M(m);
1262 
1263 		return (status);
1264 	}
1265 
1266 	sc->sc_flags |= UBT_ACL_RECV;
1267 	sc->sc_bulk_in_buffer = m;
1268 
1269 	return (USBD_NORMAL_COMPLETION);
1270 } /* ubt_bulk_in_start */
1271 
1272 /*
1273  * USB bulk-in transfer callback
1274  */
1275 
1276 static void
1277 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1278 {
1279 	ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1280 	NG_NODE_UNREF((node_p) p);
1281 } /* ubt_bulk_in_complete */
1282 
1283 static void
1284 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1285 {
1286 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1287 	usbd_xfer_handle	 h = (usbd_xfer_handle) arg1;
1288 	usbd_status		 s = (usbd_status) arg2;
1289 	struct mbuf		*m = NULL;
1290 	ng_hci_acldata_pkt_t	*hdr = NULL;
1291 	int			 len;
1292 
1293 	if (sc == NULL)
1294 		return;
1295 
1296 	KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1297 "%s: %s - No bulk-in request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1298 
1299 	sc->sc_flags &= ~UBT_ACL_RECV;
1300 
1301 	m = sc->sc_bulk_in_buffer;
1302 	sc->sc_bulk_in_buffer = NULL;
1303 
1304 	hdr = mtod(m, ng_hci_acldata_pkt_t *);
1305 
1306 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1307 		NG_UBT_INFO(
1308 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1309 
1310 		NG_FREE_M(m);
1311 		return;
1312 	}
1313 
1314 	if (s == USBD_CANCELLED) {
1315 		NG_UBT_INFO(
1316 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1317 			__func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_in_pipe);
1318 
1319 		NG_FREE_M(m);
1320 		return;
1321 	}
1322 
1323 	if (s != USBD_NORMAL_COMPLETION) {
1324 		NG_UBT_WARN(
1325 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1326 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1327 
1328 		if (s == USBD_STALLED)
1329 			usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1330 
1331 		NG_UBT_STAT_IERROR(sc->sc_stat);
1332 		NG_FREE_M(m);
1333 
1334 		return; /* XXX FIXME we should restart after some delay */
1335 	}
1336 
1337 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1338 	m->m_pkthdr.len += h->actlen;
1339 	m->m_len += h->actlen;
1340 
1341 	NG_UBT_INFO(
1342 "%s: %s - Got %d bytes from bulk-in pipe\n",
1343 		__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1344 
1345 	if (m->m_pkthdr.len < sizeof(*hdr)) {
1346 		NG_FREE_M(m);
1347 		goto done;
1348 	}
1349 
1350 	len = le16toh(hdr->length);
1351 	if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1352 		NG_UBT_INFO(
1353 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1354 			__func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len, len);
1355 
1356 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1357 
1358 		NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1359 		if (len != 0)
1360 			NG_UBT_STAT_IERROR(sc->sc_stat);
1361 	} else {
1362 		NG_UBT_ERR(
1363 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1364 			__func__, device_get_nameunit(sc->sc_dev), len,
1365 			m->m_pkthdr.len);
1366 
1367 		NG_UBT_STAT_IERROR(sc->sc_stat);
1368 		NG_FREE_M(m);
1369 	}
1370 done:
1371 	ubt_bulk_in_start(sc);
1372 } /* ubt_bulk_in_complete2 */
1373 
1374 /*
1375  * Start bulk-out USB transfer. Must be called with node locked
1376  */
1377 
1378 static usbd_status
1379 ubt_bulk_out_start(ubt_softc_p sc)
1380 {
1381 	struct mbuf	*m = NULL;
1382 	usbd_status	status;
1383 
1384 	KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1385 "%s: %s - Another bulk-out request is pending\n",
1386 		__func__, device_get_nameunit(sc->sc_dev)));
1387 
1388 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1389 	if (m == NULL) {
1390 		NG_UBT_INFO(
1391 "%s: %s - ACL data queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
1392 
1393  		return (USBD_NORMAL_COMPLETION);
1394 	}
1395 
1396 	/*
1397 	 * Check ACL data frame size and copy it back to linear USB
1398 	 * transfer buffer.
1399 	 */
1400 
1401 	if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1402 		panic(
1403 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1404 			__func__, device_get_nameunit(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1405 			m->m_pkthdr.len);
1406 
1407 	m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1408 
1409 	/* Initialize a bulk-out USB transfer and then schedule it */
1410 	usbd_setup_xfer(
1411 			sc->sc_bulk_out_xfer,
1412 			sc->sc_bulk_out_pipe,
1413 			(usbd_private_handle) sc->sc_node,
1414 			sc->sc_bulk_out_buffer,
1415 			m->m_pkthdr.len,
1416 			USBD_NO_COPY,
1417 			USBD_DEFAULT_TIMEOUT, /* XXX */
1418 			ubt_bulk_out_complete);
1419 
1420 	NG_NODE_REF(sc->sc_node);
1421 
1422 	status = usbd_transfer(sc->sc_bulk_out_xfer);
1423 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1424 		NG_UBT_ERR(
1425 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1426 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1427 			status);
1428 
1429 		NG_NODE_UNREF(sc->sc_node);
1430 
1431 		NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1432 		NG_UBT_STAT_OERROR(sc->sc_stat);
1433 
1434 		/* XXX FIXME should we try to start another transfer? */
1435 	} else {
1436 		NG_UBT_INFO(
1437 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1438 			__func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len);
1439 
1440 		sc->sc_flags |= UBT_ACL_XMIT;
1441 		status = USBD_NORMAL_COMPLETION;
1442 	}
1443 
1444 	NG_FREE_M(m);
1445 
1446 	return (status);
1447 } /* ubt_bulk_out_start */
1448 
1449 /*
1450  * USB bulk-out transfer callback
1451  */
1452 
1453 static void
1454 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1455 {
1456 	ng_send_fn((node_p) p,  NULL, ubt_bulk_out_complete2, (void *) h, s);
1457 	NG_NODE_UNREF((node_p) p);
1458 } /* ubt_bulk_out_complete */
1459 
1460 static void
1461 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1462 {
1463 	ubt_softc_p		sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1464 	usbd_xfer_handle	h = (usbd_xfer_handle) arg1;
1465 	usbd_status		s = (usbd_status) arg2;
1466 
1467 	if (sc == NULL)
1468 		return;
1469 
1470 	KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1471 "%s: %s - No bulk-out request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1472 
1473 	sc->sc_flags &= ~UBT_ACL_XMIT;
1474 
1475 	if (s == USBD_CANCELLED) {
1476 		NG_UBT_INFO(
1477 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1478 			__func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_out_pipe);
1479 
1480 		return;
1481 	}
1482 
1483 	if (s != USBD_NORMAL_COMPLETION) {
1484 		NG_UBT_WARN(
1485 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1486 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1487 
1488 		if (s == USBD_STALLED)
1489 			usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1490 
1491 		NG_UBT_STAT_OERROR(sc->sc_stat);
1492 	} else {
1493 		NG_UBT_INFO(
1494 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1495 			__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1496 
1497 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1498 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1499 	}
1500 
1501 	if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1502 		ubt_bulk_out_start(sc);
1503 } /* ubt_bulk_out_complete2 */
1504 
1505 /*
1506  * Start non-active Isochronous-in USB transfer.
1507  * Must be called with node locked
1508  */
1509 
1510 static usbd_status
1511 ubt_isoc_in_start_one(ubt_softc_p sc, int idx)
1512 {
1513 	usbd_status	status;
1514 	int		i;
1515 
1516 	for (i = 0; i < NG_UBT_NFRAMES; i++)
1517 		sc->sc_isoc_in[idx].frlen[i] = sc->sc_isoc_size;
1518 
1519 	usbd_setup_isoc_xfer(
1520 		sc->sc_isoc_in[idx].xfer,
1521 		sc->sc_isoc_in_pipe,
1522 		(usbd_private_handle) sc->sc_node,
1523 		sc->sc_isoc_in[idx].frlen,
1524 		NG_UBT_NFRAMES,
1525 		USBD_NO_COPY | USBD_SHORT_XFER_OK,
1526 		ubt_isoc_in_complete);
1527 
1528 	NG_NODE_REF(sc->sc_node);
1529 
1530 	status = usbd_transfer(sc->sc_isoc_in[idx].xfer);
1531 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1532 		NG_UBT_ERR(
1533 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1534 			__func__, device_get_nameunit(sc->sc_dev),
1535 			usbd_errstr(status), status);
1536 
1537 		NG_NODE_UNREF(sc->sc_node);
1538 	} else
1539 		sc->sc_isoc_in[idx].active = 1;
1540 
1541 	return (status);
1542 }
1543 
1544 /*
1545  * (Re)Start all non-active Isochronous-in USB transfers.
1546  * Must be called with node locked.
1547  */
1548 
1549 static usbd_status
1550 ubt_isoc_in_start(ubt_softc_p sc)
1551 {
1552 	int	i;
1553 
1554 	for (i = 0; i < NG_UBT_NXFERS; i++)
1555 		if (!sc->sc_isoc_in[i].active)
1556 			ubt_isoc_in_start_one(sc, i);
1557 
1558 	return (USBD_NORMAL_COMPLETION);
1559 } /* ubt_isoc_in_start */
1560 
1561 /*
1562  * USB isochronous transfer callback
1563  */
1564 
1565 static void
1566 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1567 {
1568 	ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1569 	NG_NODE_UNREF((node_p) p);
1570 } /* ubt_isoc_in_complete */
1571 
1572 static void
1573 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1574 {
1575 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1576 	usbd_xfer_handle	 h = (usbd_xfer_handle) arg1;
1577 	usbd_status		 s = (usbd_status) arg2;
1578 	int			 i, idx, want, got;
1579 	struct mbuf		*m;
1580 
1581 	if (sc == NULL)
1582 		return;
1583 
1584 	/* Find xfer */
1585 	idx = -1;
1586 	for (i = 0; i < NG_UBT_NXFERS; i++) {
1587 		if (sc->sc_isoc_in[i].xfer == h) {
1588 			idx = i;
1589 			break;
1590 		}
1591 	}
1592 	KASSERT(idx != -1, (
1593 "%s:%s - Could not find isoc-in request\n",
1594 		__func__, device_get_nameunit(sc->sc_dev)));
1595 	KASSERT(sc->sc_isoc_in[idx].active, (
1596 "%s: %s - Isoc-in request is not active\n",
1597 		__func__, device_get_nameunit(sc->sc_dev)));
1598 
1599 	sc->sc_isoc_in[idx].active = 0;
1600 
1601 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1602 		NG_UBT_INFO(
1603 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1604 
1605 		return;
1606 	}
1607 
1608 	/* Process xfer */
1609 	if (s == USBD_CANCELLED) {
1610 		NG_UBT_INFO(
1611 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1612 			__func__, device_get_nameunit(sc->sc_dev), sc->sc_isoc_in_pipe);
1613 
1614 		return;
1615 	}
1616 
1617 	if (s != USBD_NORMAL_COMPLETION) {
1618 		NG_UBT_WARN(
1619 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1620 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1621 
1622 		if (s == USBD_STALLED)
1623 			usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1624 
1625 		NG_UBT_STAT_IERROR(sc->sc_stat);
1626 
1627 		return; /* XXX FIXME we should restart after some delay */
1628 	}
1629 
1630 	if (h->actlen <= 0)
1631 		goto done;
1632 
1633 	NG_UBT_INFO(
1634 "%s: %s - Got %d bytes from isoc-in pipe\n",
1635 		__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1636 
1637 	/*
1638 	 * Re-assemble SCO HCI frame
1639 	 */
1640 
1641 	m = sc->sc_isoc_in_buffer;
1642 	sc->sc_isoc_in_buffer = NULL;
1643 
1644 	for (i = 0; i < NG_UBT_NFRAMES; i ++) {
1645 		uint8_t	*frame = (uint8_t *) sc->sc_isoc_in[idx].buffer +
1646 					(i * sc->sc_isoc_size);
1647 
1648 		while (sc->sc_isoc_in[idx].frlen[i] > 0) {
1649 			int	error, frlen = sc->sc_isoc_in[idx].frlen[i];
1650 
1651 			if (m == NULL) {
1652 				MGETHDR(m, M_DONTWAIT, MT_DATA);
1653 				if (m == NULL) {
1654 					goto done; /* XXX out of sync! */
1655 				}
1656 
1657 				MCLGET(m, M_DONTWAIT);
1658 				if (!(m->m_flags & M_EXT)) {
1659 					NG_FREE_M(m);
1660 					goto done; /* XXX out of sync! */
1661 				}
1662 
1663 				if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1664 					*mtod(m, uint8_t *) = NG_HCI_SCO_DATA_PKT;
1665 					m->m_pkthdr.len = m->m_len = got = 1;
1666 				} else {
1667 					m->m_pkthdr.len = m->m_len = got = 0;
1668 				}
1669 
1670 				want = sizeof(ng_hci_scodata_pkt_t);
1671 			} else {
1672 				got = m->m_pkthdr.len;
1673 				want = sizeof(ng_hci_scodata_pkt_t);
1674 
1675 				if (got >= want)
1676 					want += mtod(m, ng_hci_scodata_pkt_t *)->length;
1677 			}
1678 
1679 			if (got + frlen > want)
1680 				frlen = want - got;
1681 
1682 			if (!m_append(m, frlen, frame)) {
1683 				NG_FREE_M(m);
1684 				goto done; /* XXX out of sync! */
1685 			}
1686 
1687 			got += frlen;
1688 			frame += frlen;
1689 			sc->sc_isoc_in[idx].frlen[i] -= frlen;
1690 
1691 			if (got != want)
1692 				continue;
1693 
1694 			if (want == sizeof(ng_hci_scodata_pkt_t))
1695 				want += mtod(m, ng_hci_scodata_pkt_t *)->length;
1696 
1697 			if (got != want)
1698 				continue;
1699 
1700 			NG_UBT_INFO(
1701 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1702 				__func__, device_get_nameunit(sc->sc_dev),
1703 				m->m_pkthdr.len,
1704 				mtod(m, ng_hci_scodata_pkt_t *)->length);
1705 
1706 			NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1707 			NG_UBT_STAT_BYTES_RECV(sc->sc_stat, m->m_pkthdr.len);
1708 
1709 			NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1710 			if (error != 0)
1711 				NG_UBT_STAT_IERROR(sc->sc_stat);
1712 		}
1713 	}
1714 
1715 	sc->sc_isoc_in_buffer = m;
1716 done:
1717 	ubt_isoc_in_start_one(sc, idx);
1718 } /* ubt_isoc_in_complete2 */
1719 
1720 /*
1721  * Start non-active isochronous-out USB transfer.
1722  * Must be called with node locked
1723  */
1724 
1725 static usbd_status
1726 ubt_isoc_out_start_one(ubt_softc_p sc, int idx)
1727 {
1728 	int		 len, maxlen, size, nframes;
1729 	struct mbuf	*m;
1730 	uint8_t		*buffer;
1731 	usbd_status	 status;
1732 
1733 	/*
1734 	 * Fill the transfer buffer with data from the queue,
1735 	 * putting any leftover back on the queue
1736 	 */
1737 
1738 	len = 0;
1739  	maxlen = NG_UBT_NFRAMES * sc->sc_isoc_size;
1740 	m = NULL;
1741 	buffer = sc->sc_isoc_out[idx].buffer;
1742 
1743 	while (maxlen > 0) {
1744 		if (m == NULL) {
1745 			NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1746 			if (m == NULL)
1747 				break;
1748 		}
1749 
1750 		if (m->m_pkthdr.len > 0) {
1751 			size = MIN(m->m_pkthdr.len, maxlen);
1752 
1753 			m_copydata(m, 0, size, buffer);
1754 			m_adj(m, size);
1755 
1756 			buffer += size;
1757 			len += size;
1758 			maxlen -= size;
1759 		}
1760 
1761 		if (m->m_pkthdr.len == 0) {
1762 			NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1763 			NG_FREE_M(m);
1764 		}
1765 	}
1766 
1767 	if (m != NULL)
1768 		NG_BT_MBUFQ_PREPEND(&sc->sc_scoq, m);
1769 
1770 	if (len == 0)
1771 		return (USBD_NORMAL_COMPLETION); /* nothing to send */
1772 
1773 	NG_UBT_STAT_BYTES_SENT(sc->sc_stat, len);
1774 
1775 	/* Calculate number of isoc frames and sizes */
1776 	for (nframes = 0; len > 0; nframes ++) {
1777 		size = MIN(sc->sc_isoc_size, len);
1778 		sc->sc_isoc_out[idx].frlen[nframes] = size;
1779 		len -= size;
1780 	}
1781 
1782 	/* Initialize a isoc-out USB transfer and then schedule it */
1783 	usbd_setup_isoc_xfer(
1784 		sc->sc_isoc_out[idx].xfer,
1785 		sc->sc_isoc_out_pipe,
1786 		(usbd_private_handle) sc->sc_node,
1787 		sc->sc_isoc_out[idx].frlen,
1788 		nframes,
1789 		USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1790 		ubt_isoc_out_complete);
1791 
1792 	NG_NODE_REF(sc->sc_node);
1793 	sc->sc_isoc_out[idx].active = 1;
1794 
1795 	status = usbd_transfer(sc->sc_isoc_out[idx].xfer);
1796 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1797 		NG_UBT_ERR(
1798 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1799 			__func__, device_get_nameunit(sc->sc_dev),
1800 			usbd_errstr(status), status);
1801 
1802 		sc->sc_isoc_out[idx].active = 0;
1803 		NG_NODE_UNREF(sc->sc_node);
1804 
1805 		NG_UBT_STAT_OERROR(sc->sc_stat);
1806 	} else {
1807 		NG_UBT_INFO(
1808 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1809 			__func__, device_get_nameunit(sc->sc_dev), nframes,
1810 			sc->sc_isoc_size);
1811 		status = USBD_NORMAL_COMPLETION;
1812 	}
1813 
1814 	return (status);
1815 }
1816 
1817 /*
1818  * Start all non-active isochronous-out USB transfer.
1819  * Must be called with node locked
1820  */
1821 
1822 static usbd_status
1823 ubt_isoc_out_start(ubt_softc_p sc)
1824 {
1825 	int	i;
1826 
1827 	for (i = 0; i < NG_UBT_NXFERS; i++) {
1828 		if (sc->sc_isoc_out[i].active)
1829 			continue;
1830 
1831 		ubt_isoc_out_start_one(sc, i);
1832 	}
1833 
1834 	return (USBD_NORMAL_COMPLETION);
1835 } /* ubt_isoc_out_start */
1836 
1837 /*
1838  * USB isoc-out. transfer callback
1839  */
1840 
1841 static void
1842 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1843 {
1844 	ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1845 	NG_NODE_UNREF((node_p) p);
1846 } /* ubt_isoc_out_complete */
1847 
1848 static void
1849 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1850 {
1851 	ubt_softc_p		sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1852 	usbd_xfer_handle	h = (usbd_xfer_handle) arg1;
1853 	usbd_status		s = (usbd_status) arg2;
1854 	int			i, idx;
1855 
1856 	if (sc == NULL)
1857 		return;
1858 
1859 	/* Find xfer */
1860 	idx = -1;
1861 	for (i = 0; i < NG_UBT_NXFERS; i++) {
1862 		if (sc->sc_isoc_out[i].xfer == h) {
1863 			idx = i;
1864 			break;
1865 		}
1866 	}
1867 	KASSERT(idx != -1, (
1868 "%s:%s - Could not find isoc-out request\n",
1869 		__func__, device_get_nameunit(sc->sc_dev)));
1870 	KASSERT(sc->sc_isoc_out[idx].active, (
1871 "%s: %s - Isoc-out request is not active\n",
1872 		__func__, device_get_nameunit(sc->sc_dev)));
1873 
1874 	sc->sc_isoc_out[idx].active = 0;
1875 
1876 	/* Process xfer */
1877 	if (s == USBD_CANCELLED) {
1878 		NG_UBT_INFO(
1879 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1880 			__func__, device_get_nameunit(sc->sc_dev),
1881 			sc->sc_isoc_out_pipe);
1882 
1883 		return;
1884 	}
1885 
1886 	if (s != USBD_NORMAL_COMPLETION) {
1887 		NG_UBT_WARN(
1888 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1889 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1890 
1891 		if (s == USBD_STALLED)
1892 			usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1893 
1894 		NG_UBT_STAT_OERROR(sc->sc_stat);
1895 	} else {
1896 		NG_UBT_INFO(
1897 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1898 			__func__, device_get_nameunit(sc->sc_dev), h->actlen);
1899 
1900 /* XXX FIXME	NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1901 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat); */
1902 	}
1903 
1904 	if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1905 		ubt_isoc_out_start(sc);
1906 } /* ubt_isoc_out_complete2 */
1907 
1908 /*
1909  * Abort transfers on all USB pipes
1910  */
1911 
1912 static void
1913 ubt_reset(ubt_softc_p sc)
1914 {
1915 	/* Interrupt */
1916 	if (sc->sc_intr_pipe != NULL)
1917 		usbd_abort_pipe(sc->sc_intr_pipe);
1918 
1919 	/* Bulk-in/out */
1920 	if (sc->sc_bulk_in_pipe != NULL)
1921 		usbd_abort_pipe(sc->sc_bulk_in_pipe);
1922 	if (sc->sc_bulk_out_pipe != NULL)
1923 		usbd_abort_pipe(sc->sc_bulk_out_pipe);
1924 
1925 	/* Isoc-in/out */
1926 	if (sc->sc_isoc_in_pipe != NULL)
1927 		usbd_abort_pipe(sc->sc_isoc_in_pipe);
1928 	if (sc->sc_isoc_out_pipe != NULL)
1929 		usbd_abort_pipe(sc->sc_isoc_out_pipe);
1930 
1931 	/* Cleanup queues */
1932 	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1933 	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1934 	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1935 } /* ubt_reset */
1936 
1937 /****************************************************************************
1938  ****************************************************************************
1939  **                        Netgraph specific
1940  ****************************************************************************
1941  ****************************************************************************/
1942 
1943 /*
1944  * Netgraph node constructor. Do not allow to create node of this type.
1945  */
1946 
1947 static int
1948 ng_ubt_constructor(node_p node)
1949 {
1950 	return (EINVAL);
1951 } /* ng_ubt_constructor */
1952 
1953 /*
1954  * Netgraph node destructor. Destroy node only when device has been detached
1955  */
1956 
1957 static int
1958 ng_ubt_shutdown(node_p node)
1959 {
1960 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1961 
1962 	/* Let old node go */
1963 	NG_NODE_SET_PRIVATE(node, NULL);
1964 	NG_NODE_UNREF(node);
1965 
1966 	if (sc == NULL)
1967 		goto done;
1968 
1969 	/* Create Netgraph node */
1970 	if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1971 		printf("%s: Could not create Netgraph node\n",
1972 			device_get_nameunit(sc->sc_dev));
1973 		sc->sc_node = NULL;
1974 		goto done;
1975 	}
1976 
1977 	/* Name node */
1978 	if (ng_name_node(sc->sc_node, device_get_nameunit(sc->sc_dev)) != 0) {
1979 		printf("%s: Could not name Netgraph node\n",
1980 			device_get_nameunit(sc->sc_dev));
1981 		NG_NODE_UNREF(sc->sc_node);
1982 		sc->sc_node = NULL;
1983 		goto done;
1984 	}
1985 
1986 	NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1987 	NG_NODE_FORCE_WRITER(sc->sc_node);
1988 done:
1989 	return (0);
1990 } /* ng_ubt_shutdown */
1991 
1992 /*
1993  * Create new hook. There can only be one.
1994  */
1995 
1996 static int
1997 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1998 {
1999 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
2000 
2001 	if (strcmp(name, NG_UBT_HOOK) != 0)
2002 		return (EINVAL);
2003 
2004 	if (sc->sc_hook != NULL)
2005 		return (EISCONN);
2006 
2007 	sc->sc_hook = hook;
2008 
2009 	return (0);
2010 } /* ng_ubt_newhook */
2011 
2012 /*
2013  * Connect hook. Start incoming USB transfers
2014  */
2015 
2016 static int
2017 ng_ubt_connect(hook_p hook)
2018 {
2019 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2020 	usbd_status	status;
2021 
2022 	NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
2023 
2024 	/* Start intr transfer */
2025 	status = ubt_intr_start(sc);
2026 	if (status != USBD_NORMAL_COMPLETION) {
2027 		NG_UBT_ALERT(
2028 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
2029 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
2030 			status);
2031 		goto fail;
2032 	}
2033 
2034 	/* Start bulk-in transfer */
2035 	status = ubt_bulk_in_start(sc);
2036 	if (status != USBD_NORMAL_COMPLETION) {
2037 		NG_UBT_ALERT(
2038 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
2039 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
2040 			status);
2041 		goto fail;
2042 	}
2043 
2044 	/* Start isoc-in transfer */
2045 	status = ubt_isoc_in_start(sc);
2046 	if (status != USBD_NORMAL_COMPLETION) {
2047 		NG_UBT_ALERT(
2048 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
2049 			__func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
2050 			status);
2051 		goto fail;
2052 	}
2053 
2054 	return (0);
2055 fail:
2056 	ubt_reset(sc);
2057 	sc->sc_hook = NULL;
2058 
2059 	return (ENXIO);
2060 } /* ng_ubt_connect */
2061 
2062 /*
2063  * Disconnect hook
2064  */
2065 
2066 static int
2067 ng_ubt_disconnect(hook_p hook)
2068 {
2069 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2070 
2071 	if (sc != NULL) {
2072 		if (hook != sc->sc_hook)
2073 			return (EINVAL);
2074 
2075 		ubt_reset(sc);
2076 		sc->sc_hook = NULL;
2077 	}
2078 
2079 	return (0);
2080 } /* ng_ubt_disconnect */
2081 
2082 /*
2083  * Process control message
2084  */
2085 
2086 static int
2087 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
2088 {
2089 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
2090 	struct ng_mesg		*msg = NULL, *rsp = NULL;
2091 	struct ng_bt_mbufq	*q = NULL;
2092 	int			 error = 0, queue, qlen;
2093 
2094 	if (sc == NULL) {
2095 		NG_FREE_ITEM(item);
2096 		return (EHOSTDOWN);
2097 	}
2098 
2099 	NGI_GET_MSG(item, msg);
2100 
2101 	switch (msg->header.typecookie) {
2102 	case NGM_GENERIC_COOKIE:
2103 		switch (msg->header.cmd) {
2104 		case NGM_TEXT_STATUS:
2105 			NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
2106 			if (rsp == NULL)
2107 				error = ENOMEM;
2108 			else
2109 				snprintf(rsp->data, NG_TEXTRESPONSE,
2110 					"Hook: %s\n"   \
2111 					"Flags: %#x\n" \
2112 					"Debug: %d\n"  \
2113 					"CMD queue: [have:%d,max:%d]\n" \
2114 					"ACL queue: [have:%d,max:%d]\n" \
2115 					"SCO queue: [have:%d,max:%d]",
2116 					(sc->sc_hook != NULL)? NG_UBT_HOOK : "",
2117 					sc->sc_flags,
2118 					sc->sc_debug,
2119 					NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
2120 					sc->sc_cmdq.maxlen,
2121 					NG_BT_MBUFQ_LEN(&sc->sc_aclq),
2122 					sc->sc_aclq.maxlen,
2123 					NG_BT_MBUFQ_LEN(&sc->sc_scoq),
2124 					sc->sc_scoq.maxlen);
2125 			break;
2126 
2127 		default:
2128 			error = EINVAL;
2129 			break;
2130 		}
2131 		break;
2132 
2133 	case NGM_UBT_COOKIE:
2134 		switch (msg->header.cmd) {
2135 		case NGM_UBT_NODE_SET_DEBUG:
2136 			if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2137 				error = EMSGSIZE;
2138 			else
2139 				sc->sc_debug =
2140 					*((ng_ubt_node_debug_ep *)(msg->data));
2141 			break;
2142 
2143 		case NGM_UBT_NODE_GET_DEBUG:
2144 			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2145 				M_NOWAIT);
2146 			if (rsp == NULL)
2147 				error = ENOMEM;
2148 			else
2149 				*((ng_ubt_node_debug_ep *)(rsp->data)) =
2150 					sc->sc_debug;
2151                         break;
2152 
2153 		case NGM_UBT_NODE_SET_QLEN:
2154 			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2155 				error = EMSGSIZE;
2156 			else {
2157 				queue = ((ng_ubt_node_qlen_ep *)
2158 						(msg->data))->queue;
2159 				qlen = ((ng_ubt_node_qlen_ep *)
2160 						(msg->data))->qlen;
2161 
2162 				if (qlen <= 0) {
2163 					error = EINVAL;
2164 					break;
2165 				}
2166 
2167 				switch (queue) {
2168 				case NGM_UBT_NODE_QUEUE_CMD:
2169 					q = &sc->sc_cmdq;
2170 					break;
2171 
2172 				case NGM_UBT_NODE_QUEUE_ACL:
2173 					q = &sc->sc_aclq;
2174 					break;
2175 
2176 				case NGM_UBT_NODE_QUEUE_SCO:
2177 					q = &sc->sc_scoq;
2178 					break;
2179 
2180 				default:
2181 					q = NULL;
2182 					error = EINVAL;
2183 					break;
2184 				}
2185 
2186 				if (q != NULL)
2187 					q->maxlen = qlen;
2188 			}
2189 			break;
2190 
2191 		case NGM_UBT_NODE_GET_QLEN:
2192 			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2193 				error = EMSGSIZE;
2194 				break;
2195 			}
2196 
2197 			queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2198 			switch (queue) {
2199 			case NGM_UBT_NODE_QUEUE_CMD:
2200 				q = &sc->sc_cmdq;
2201 				break;
2202 
2203 			case NGM_UBT_NODE_QUEUE_ACL:
2204 				q = &sc->sc_aclq;
2205 				break;
2206 
2207 			case NGM_UBT_NODE_QUEUE_SCO:
2208 				q = &sc->sc_scoq;
2209 				break;
2210 
2211 			default:
2212 				q = NULL;
2213 				error = EINVAL;
2214 				break;
2215 			}
2216 
2217 			if (q != NULL) {
2218 				NG_MKRESPONSE(rsp, msg,
2219 					sizeof(ng_ubt_node_qlen_ep), M_NOWAIT);
2220 				if (rsp == NULL) {
2221 					error = ENOMEM;
2222 					break;
2223 				}
2224 
2225 				((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2226 					queue;
2227 				((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2228 					q->maxlen;
2229 			}
2230 			break;
2231 
2232 		case NGM_UBT_NODE_GET_STAT:
2233 			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2234 				M_NOWAIT);
2235 			if (rsp == NULL)
2236 				error = ENOMEM;
2237 			else
2238 				bcopy(&sc->sc_stat, rsp->data,
2239 					sizeof(ng_ubt_node_stat_ep));
2240 			break;
2241 
2242 		case NGM_UBT_NODE_RESET_STAT:
2243 			NG_UBT_STAT_RESET(sc->sc_stat);
2244 			break;
2245 
2246 		default:
2247 			error = EINVAL;
2248 			break;
2249 		}
2250 		break;
2251 
2252 	default:
2253 		error = EINVAL;
2254 		break;
2255 	}
2256 
2257 	NG_RESPOND_MSG(error, node, item, rsp);
2258 	NG_FREE_MSG(msg);
2259 
2260 	return (error);
2261 } /* ng_ubt_rcvmsg */
2262 
2263 /*
2264  * Process data
2265  */
2266 
2267 static int
2268 ng_ubt_rcvdata(hook_p hook, item_p item)
2269 {
2270 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2271 	struct mbuf		*m = NULL;
2272 	usbd_status		(*f)(ubt_softc_p) = NULL;
2273 	struct ng_bt_mbufq	*q = NULL;
2274 	int			 b, error = 0;
2275 
2276 	if (sc == NULL) {
2277 		error = EHOSTDOWN;
2278 		goto done;
2279 	}
2280 
2281 	if (hook != sc->sc_hook) {
2282 		error = EINVAL;
2283 		goto done;
2284 	}
2285 
2286 	/* Deatch mbuf and get HCI frame type */
2287 	NGI_GET_M(item, m);
2288 
2289 	/* Process HCI frame */
2290 	switch (*mtod(m, uint8_t *)) { /* XXX call m_pullup ? */
2291 	case NG_HCI_CMD_PKT:
2292 		f = ubt_request_start;
2293 		q = &sc->sc_cmdq;
2294 		b = UBT_CMD_XMIT;
2295 		break;
2296 
2297 	case NG_HCI_ACL_DATA_PKT:
2298 		f = ubt_bulk_out_start;
2299 		q = &sc->sc_aclq;
2300 		b = UBT_ACL_XMIT;
2301 		break;
2302 
2303 	case NG_HCI_SCO_DATA_PKT:
2304 		f = ubt_isoc_out_start;
2305 		q = &sc->sc_scoq;
2306 		b = UBT_SCO_XMIT;
2307 		break;
2308 
2309 	default:
2310 		NG_UBT_ERR(
2311 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2312 			__func__, device_get_nameunit(sc->sc_dev), *mtod(m, uint8_t *),
2313 			m->m_pkthdr.len);
2314 
2315 		NG_FREE_M(m);
2316 		error = EINVAL;
2317 
2318 		goto done;
2319 		/* NOT REACHED */
2320 	}
2321 
2322 	/* Loose frame type, if required */
2323 	if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2324 		m_adj(m, sizeof(uint8_t));
2325 
2326 	if (NG_BT_MBUFQ_FULL(q)) {
2327 		NG_UBT_ERR(
2328 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2329 			__func__, device_get_nameunit(sc->sc_dev),
2330 			*mtod(m, uint8_t *), m->m_pkthdr.len);
2331 
2332 		NG_FREE_M(m);
2333 	} else
2334 		NG_BT_MBUFQ_ENQUEUE(q, m);
2335 
2336 	if (!(sc->sc_flags & b))
2337 		if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2338 			error = EIO;
2339 done:
2340 	NG_FREE_ITEM(item);
2341 
2342 	return (error);
2343 } /* ng_ubt_rcvdata */
2344 
2345