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