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