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