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