xref: /freebsd/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c (revision f0adf7f5cdd241db2f2c817683191a6ef64a4e95)
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.16 2003/10/10 19:15:06 max Exp $
29  * $FreeBSD$
30  */
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/conf.h>
36 #include <sys/endian.h>
37 #include <sys/filio.h>
38 #include <sys/fcntl.h>
39 #include <sys/mbuf.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/poll.h>
44 #include <sys/uio.h>
45 #include <machine/bus.h>
46 
47 #include <dev/usb/usb.h>
48 #include <dev/usb/usbdi.h>
49 #include <dev/usb/usbdi_util.h>
50 #include <dev/usb/usbdivar.h>
51 
52 #include <netgraph/ng_message.h>
53 #include <netgraph/netgraph.h>
54 #include <netgraph/ng_parse.h>
55 #include <netgraph/bluetooth/include/ng_bluetooth.h>
56 #include <netgraph/bluetooth/include/ng_hci.h>
57 #include <netgraph/bluetooth/include/ng_ubt.h>
58 #include <netgraph/bluetooth/drivers/ubt/ng_ubt_var.h>
59 
60 #include "usbdevs.h"
61 
62 /*
63  * USB methods
64  */
65 
66 USB_DECLARE_DRIVER(ubt);
67 
68 Static int         ubt_modevent		  (module_t, int, void *);
69 
70 Static usbd_status ubt_request_start      (ubt_softc_p);
71 Static void        ubt_request_complete   (usbd_xfer_handle,
72 					   usbd_private_handle, usbd_status);
73 Static void        ubt_request_complete2  (node_p, hook_p, void *, int);
74 
75 Static usbd_status ubt_intr_start	  (ubt_softc_p);
76 Static void        ubt_intr_complete      (usbd_xfer_handle,
77 					   usbd_private_handle, usbd_status);
78 Static void        ubt_intr_complete2     (node_p, hook_p, void *, int);
79 
80 Static usbd_status ubt_bulk_in_start	  (ubt_softc_p);
81 Static void        ubt_bulk_in_complete   (usbd_xfer_handle,
82 					   usbd_private_handle, usbd_status);
83 Static void        ubt_bulk_in_complete2  (node_p, hook_p, void *, int);
84 
85 Static usbd_status ubt_bulk_out_start     (ubt_softc_p);
86 Static void        ubt_bulk_out_complete  (usbd_xfer_handle,
87 					   usbd_private_handle, usbd_status);
88 Static void        ubt_bulk_out_complete2 (node_p, hook_p, void *, int);
89 
90 Static usbd_status ubt_isoc_in_start      (ubt_softc_p);
91 Static void        ubt_isoc_in_complete   (usbd_xfer_handle,
92 					   usbd_private_handle, usbd_status);
93 Static void        ubt_isoc_in_complete2  (node_p, hook_p, void *, int);
94 
95 Static usbd_status ubt_isoc_out_start     (ubt_softc_p);
96 Static void        ubt_isoc_out_complete  (usbd_xfer_handle,
97 					   usbd_private_handle, usbd_status);
98 Static void        ubt_isoc_out_complete2 (node_p, hook_p, void *, int);
99 
100 Static void        ubt_reset              (ubt_softc_p);
101 
102 /*
103  * Netgraph methods
104  */
105 
106 Static ng_constructor_t	ng_ubt_constructor;
107 Static ng_shutdown_t	ng_ubt_shutdown;
108 Static ng_newhook_t	ng_ubt_newhook;
109 Static ng_connect_t	ng_ubt_connect;
110 Static ng_disconnect_t	ng_ubt_disconnect;
111 Static ng_rcvmsg_t	ng_ubt_rcvmsg;
112 Static ng_rcvdata_t	ng_ubt_rcvdata;
113 
114 /* Queue length */
115 Static const struct ng_parse_struct_field	ng_ubt_node_qlen_type_fields[] =
116 {
117 	{ "queue", &ng_parse_int32_type, },
118 	{ "qlen",  &ng_parse_int32_type, },
119 	{ NULL, }
120 };
121 Static const struct ng_parse_type		ng_ubt_node_qlen_type = {
122 	&ng_parse_struct_type,
123 	&ng_ubt_node_qlen_type_fields
124 };
125 
126 /* Stat info */
127 Static const struct ng_parse_struct_field	ng_ubt_node_stat_type_fields[] =
128 {
129 	{ "pckts_recv", &ng_parse_uint32_type, },
130 	{ "bytes_recv", &ng_parse_uint32_type, },
131 	{ "pckts_sent", &ng_parse_uint32_type, },
132 	{ "bytes_sent", &ng_parse_uint32_type, },
133 	{ "oerrors",    &ng_parse_uint32_type, },
134 	{ "ierrors",    &ng_parse_uint32_type, },
135 	{ NULL, }
136 };
137 Static const struct ng_parse_type	ng_ubt_node_stat_type = {
138 	&ng_parse_struct_type,
139 	&ng_ubt_node_stat_type_fields
140 };
141 
142 /* Netgraph node command list */
143 Static const struct ng_cmdlist	ng_ubt_cmdlist[] = {
144 {
145 	NGM_UBT_COOKIE,
146 	NGM_UBT_NODE_SET_DEBUG,
147 	"set_debug",
148 	&ng_parse_uint16_type,
149 	NULL
150 },
151 {
152 	NGM_UBT_COOKIE,
153 	NGM_UBT_NODE_GET_DEBUG,
154 	"get_debug",
155 	NULL,
156 	&ng_parse_uint16_type
157 },
158 {
159 	NGM_UBT_COOKIE,
160 	NGM_UBT_NODE_SET_QLEN,
161 	"set_qlen",
162 	&ng_ubt_node_qlen_type,
163 	NULL
164 },
165 {
166 	NGM_UBT_COOKIE,
167 	NGM_UBT_NODE_GET_QLEN,
168 	"get_qlen",
169 	&ng_ubt_node_qlen_type,
170 	&ng_ubt_node_qlen_type
171 },
172 {
173 	NGM_UBT_COOKIE,
174 	NGM_UBT_NODE_GET_STAT,
175 	"get_stat",
176 	NULL,
177 	&ng_ubt_node_stat_type
178 },
179 {
180 	NGM_UBT_COOKIE,
181 	NGM_UBT_NODE_RESET_STAT,
182 	"reset_stat",
183         NULL,
184 	NULL
185 },
186 {
187 	NGM_UBT_COOKIE,
188 	NGM_UBT_NODE_DEV_NODES,
189 	"dev_nodes",
190         &ng_parse_uint16_type,
191 	NULL
192 },
193 { 0, }
194 };
195 
196 /* Netgraph node type */
197 Static struct ng_type	typestruct = {
198 	.version =	NG_ABI_VERSION,
199 	.name =		NG_UBT_NODE_TYPE,
200 	.constructor =	ng_ubt_constructor,
201 	.rcvmsg =	ng_ubt_rcvmsg,
202 	.shutdown =	ng_ubt_shutdown,
203 	.newhook =	ng_ubt_newhook,
204 	.connect =	ng_ubt_connect,
205 	.rcvdata =	ng_ubt_rcvdata,
206 	.disconnect =	ng_ubt_disconnect,
207 	.cmdlist =	ng_ubt_cmdlist
208 };
209 
210 /*
211  * Device methods
212  */
213 
214 #define UBT_UNIT(n)	((minor(n) >> 4) & 0xf)
215 #define UBT_ENDPOINT(n)	(minor(n) & 0xf)
216 #define UBT_MINOR(u, e)	(((u) << 4) | (e))
217 #define UBT_BSIZE	1024
218 
219 Static d_open_t		ubt_open;
220 Static d_close_t	ubt_close;
221 Static d_read_t		ubt_read;
222 Static d_write_t	ubt_write;
223 Static d_ioctl_t	ubt_ioctl;
224 Static d_poll_t		ubt_poll;
225 Static void		ubt_create_device_nodes  (ubt_softc_p);
226 Static void		ubt_destroy_device_nodes (ubt_softc_p);
227 
228 Static struct cdevsw	ubt_cdevsw = {
229 	.d_version =	D_VERSION,
230 	.d_flags =	D_NEEDGIANT,
231 	.d_open =	ubt_open,
232 	.d_close =	ubt_close,
233 	.d_read =	ubt_read,
234 	.d_write =	ubt_write,
235 	.d_ioctl =	ubt_ioctl,
236 	.d_poll =	ubt_poll,
237 	.d_name =	"ubt",
238 };
239 
240 /*
241  * Module
242  */
243 
244 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
245 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
246 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
247 
248 /****************************************************************************
249  ****************************************************************************
250  **                              USB specific
251  ****************************************************************************
252  ****************************************************************************/
253 
254 /*
255  * Load/Unload the driver module
256  */
257 
258 Static int
259 ubt_modevent(module_t mod, int event, void *data)
260 {
261 	int	error;
262 
263 	switch (event) {
264 	case MOD_LOAD:
265 		error = ng_newtype(&typestruct);
266 		if (error != 0)
267 			printf(
268 "%s: Could not register Netgraph node type, error=%d\n",
269 				NG_UBT_NODE_TYPE, error);
270 		else
271 			error = usbd_driver_load(mod, event, data);
272 		break;
273 
274 	case MOD_UNLOAD:
275 		error = ng_rmtype(&typestruct);
276 		if (error == 0)
277 			error = usbd_driver_load(mod, event, data);
278 		break;
279 
280 	default:
281 		error = EOPNOTSUPP;
282 		break;
283 	}
284 
285 	return (error);
286 } /* ubt_modevent */
287 
288 /*
289  * Probe for a USB Bluetooth device
290  */
291 
292 USB_MATCH(ubt)
293 {
294 	/*
295 	 * If for some reason device should not be attached then put
296 	 * VendorID/ProductID pair into the list below. Currently I
297 	 * do not know of any such devices. The format is as follows:
298 	 *
299 	 *	{ VENDOR_ID, PRODUCT_ID },
300 	 *
301 	 * where VENDOR_ID and PRODUCT_ID are hex numbers.
302 	 */
303 
304 	Static struct usb_devno const	ubt_ignored_devices[] = {
305 		{ 0, 0 } /* This should be the last item in the list */
306 	};
307 
308 	/*
309 	 * If device violates Bluetooth specification and has bDeviceClass,
310 	 * bDeviceSubClass and bDeviceProtocol set to wrong values then you
311 	 * could try to put VendorID/ProductID pair into the list below.
312 	 * Currently I do not know of any such devices.
313 	 */
314 
315 	Static struct usb_devno const	ubt_broken_devices[] = {
316 		{ 0, 0 } /* This should be the last item in the list */
317 	};
318 
319 	USB_MATCH_START(ubt, uaa);
320 
321 	usb_device_descriptor_t	*dd = usbd_get_device_descriptor(uaa->device);
322 
323 	if (uaa->iface == NULL ||
324 	    usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
325 		return (UMATCH_NONE);
326 
327 	if (dd->bDeviceClass == UDCLASS_WIRELESS &&
328 	    dd->bDeviceSubClass == UDSUBCLASS_RF &&
329 	    dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
330 		return (UMATCH_DEVCLASS_DEVSUBCLASS);
331 
332 	if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
333 		return (UMATCH_VENDOR_PRODUCT);
334 
335 	return (UMATCH_NONE);
336 } /* USB_MATCH(ubt) */
337 
338 /*
339  * Attach the device
340  */
341 
342 USB_ATTACH(ubt)
343 {
344 	USB_ATTACH_START(ubt, sc, uaa);
345 	usb_config_descriptor_t		*cd = NULL;
346 	usb_interface_descriptor_t	*id = NULL;
347 	usb_endpoint_descriptor_t	*ed = NULL;
348 	char				 devinfo[UBT_BSIZE];
349 	usbd_status			 error;
350 	int				 i, ai, alt_no, isoc_in, isoc_out,
351 					 isoc_isize, isoc_osize;
352 
353 	/* Get USB device info */
354 	sc->sc_udev = uaa->device;
355 	usbd_devinfo(sc->sc_udev, 0, devinfo);
356 	USB_ATTACH_SETUP;
357 	printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
358 
359 	/*
360 	 * Initialize device softc structure
361 	 */
362 
363 	/* State */
364 	sc->sc_debug = NG_UBT_WARN_LEVEL;
365 	sc->sc_flags = 0;
366 	NG_UBT_STAT_RESET(sc->sc_stat);
367 
368 	/* Interfaces */
369 	sc->sc_iface0 = sc->sc_iface1 = NULL;
370 
371 	/* Interrupt pipe */
372 	sc->sc_intr_ep = -1;
373 	sc->sc_intr_pipe = NULL;
374 	sc->sc_intr_xfer = NULL;
375 	sc->sc_intr_buffer = NULL;
376 
377 	/* Control pipe */
378 	sc->sc_ctrl_xfer = NULL;
379 	sc->sc_ctrl_buffer = NULL;
380 	NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
381 
382 	/* Bulk-in pipe */
383 	sc->sc_bulk_in_ep = -1;
384 	sc->sc_bulk_in_pipe = NULL;
385 	sc->sc_bulk_in_xfer = NULL;
386 	sc->sc_bulk_in_buffer = NULL;
387 
388 	/* Bulk-out pipe */
389 	sc->sc_bulk_out_ep = -1;
390 	sc->sc_bulk_out_pipe = NULL;
391 	sc->sc_bulk_out_xfer = NULL;
392 	sc->sc_bulk_out_buffer = NULL;
393 	NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
394 
395 	/* Isoc-in pipe */
396 	sc->sc_isoc_in_ep = -1;
397 	sc->sc_isoc_in_pipe = NULL;
398 	sc->sc_isoc_in_xfer = NULL;
399 
400 	/* Isoc-out pipe */
401 	sc->sc_isoc_out_ep = -1;
402 	sc->sc_isoc_out_pipe = NULL;
403 	sc->sc_isoc_out_xfer = NULL;
404 	sc->sc_isoc_size = -1;
405 	NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
406 
407 	/* Netgraph part */
408 	sc->sc_node = NULL;
409 	sc->sc_hook = NULL;
410 
411 	/* Device part */
412 	sc->sc_ctrl_dev = sc->sc_intr_dev = sc->sc_bulk_dev = NULL;
413 	sc->sc_refcnt = sc->sc_dying = 0;
414 
415 	/*
416 	 * XXX set configuration?
417 	 *
418 	 * Configure Bluetooth USB device. Discover all required USB interfaces
419 	 * and endpoints.
420 	 *
421 	 * USB device must present two interfaces:
422 	 * 1) Interface 0 that has 3 endpoints
423 	 *	1) Interrupt endpoint to receive HCI events
424 	 *	2) Bulk IN endpoint to receive ACL data
425 	 *	3) Bulk OUT endpoint to send ACL data
426 	 *
427 	 * 2) Interface 1 then has 2 endpoints
428 	 *	1) Isochronous IN endpoint to receive SCO data
429  	 *	2) Isochronous OUT endpoint to send SCO data
430 	 *
431 	 * Interface 1 (with isochronous endpoints) has several alternate
432 	 * configurations with different packet size.
433 	 */
434 
435 	/*
436 	 * Interface 0
437 	 */
438 
439 	error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
440 	if (error || sc->sc_iface0 == NULL) {
441 		printf("%s: Could not get interface 0 handle. %s (%d), " \
442 			"handle=%p\n", USBDEVNAME(sc->sc_dev),
443 			usbd_errstr(error), error, sc->sc_iface0);
444 		goto bad;
445 	}
446 
447 	id = usbd_get_interface_descriptor(sc->sc_iface0);
448 	if (id == NULL) {
449 		printf("%s: Could not get interface 0 descriptor\n",
450 			USBDEVNAME(sc->sc_dev));
451 		goto bad;
452 	}
453 
454 	for (i = 0; i < id->bNumEndpoints; i ++) {
455 		ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
456 		if (ed == NULL) {
457 			printf("%s: Could not read endpoint descriptor for " \
458 				"interface 0, i=%d\n", USBDEVNAME(sc->sc_dev),
459 				i);
460 			goto bad;
461 		}
462 
463 		switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
464 		case UE_BULK:
465 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
466 				sc->sc_bulk_in_ep = ed->bEndpointAddress;
467 			else
468 				sc->sc_bulk_out_ep = ed->bEndpointAddress;
469 			break;
470 
471 		case UE_INTERRUPT:
472 			sc->sc_intr_ep = ed->bEndpointAddress;
473 			break;
474 		}
475 	}
476 
477 	/* Check if we got everything we wanted on Interface 0 */
478 	if (sc->sc_intr_ep == -1) {
479 		printf("%s: Could not detect interrupt endpoint\n",
480 			USBDEVNAME(sc->sc_dev));
481 		goto bad;
482 	}
483 	if (sc->sc_bulk_in_ep == -1) {
484 		printf("%s: Could not detect bulk-in endpoint\n",
485 			USBDEVNAME(sc->sc_dev));
486 		goto bad;
487 	}
488 	if (sc->sc_bulk_out_ep == -1) {
489 		printf("%s: Could not detect bulk-out endpoint\n",
490 			USBDEVNAME(sc->sc_dev));
491 		goto bad;
492 	}
493 
494 	printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
495 		"bulk-out=%#x\n", USBDEVNAME(sc->sc_dev),
496 		sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
497 
498 	/*
499 	 * Interface 1
500 	 */
501 
502 	cd = usbd_get_config_descriptor(sc->sc_udev);
503 	if (cd == NULL) {
504 		printf("%s: Could not get device configuration descriptor\n",
505 			USBDEVNAME(sc->sc_dev));
506 		goto bad;
507 	}
508 
509 	error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
510 	if (error || sc->sc_iface1 == NULL) {
511 		printf("%s: Could not get interface 1 handle. %s (%d), " \
512 			"handle=%p\n", USBDEVNAME(sc->sc_dev),
513 			usbd_errstr(error), error, sc->sc_iface1);
514 		goto bad;
515 	}
516 
517 	id = usbd_get_interface_descriptor(sc->sc_iface1);
518 	if (id == NULL) {
519 		printf("%s: Could not get interface 1 descriptor\n",
520 			USBDEVNAME(sc->sc_dev));
521 		goto bad;
522 	}
523 
524 	/*
525 	 * Scan all alternate configurations for interface 1
526 	 */
527 
528 	alt_no = -1;
529 
530 	for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++)  {
531 		error = usbd_set_interface(sc->sc_iface1, ai);
532 		if (error) {
533 			printf("%s: [SCAN] Could not set alternate " \
534 				"configuration %d for interface 1. %s (%d)\n",
535 				USBDEVNAME(sc->sc_dev),  ai, usbd_errstr(error),
536 				error);
537 			goto bad;
538 		}
539 		id = usbd_get_interface_descriptor(sc->sc_iface1);
540 		if (id == NULL) {
541 			printf("%s: Could not get interface 1 descriptor for " \
542 				"alternate configuration %d\n",
543 				USBDEVNAME(sc->sc_dev), ai);
544 			goto bad;
545 		}
546 
547 		isoc_in = isoc_out = -1;
548 		isoc_isize = isoc_osize = 0;
549 
550 		for (i = 0; i < id->bNumEndpoints; i ++) {
551 			ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
552 			if (ed == NULL) {
553 				printf("%s: Could not read endpoint " \
554 					"descriptor for interface 1, " \
555 					"alternate configuration %d, i=%d\n",
556 					USBDEVNAME(sc->sc_dev), ai, i);
557 				goto bad;
558 			}
559 
560 			if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
561 				continue;
562 
563 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
564 				isoc_in = ed->bEndpointAddress;
565 				isoc_isize = UGETW(ed->wMaxPacketSize);
566 			} else {
567 				isoc_out = ed->bEndpointAddress;
568 				isoc_osize = UGETW(ed->wMaxPacketSize);
569 			}
570 		}
571 
572 		/*
573 		 * Make sure that configuration looks sane and if so
574 		 * update current settings
575 		 */
576 
577 		if (isoc_in != -1 && isoc_out != -1 &&
578 		    isoc_isize > 0  && isoc_osize > 0 &&
579 		    isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
580 			sc->sc_isoc_in_ep = isoc_in;
581 			sc->sc_isoc_out_ep = isoc_out;
582 			sc->sc_isoc_size = isoc_isize;
583 			alt_no = ai;
584 		}
585 	}
586 
587 	/* Check if we got everything we wanted on Interface 0 */
588 	if (sc->sc_isoc_in_ep == -1) {
589 		printf("%s: Could not detect isoc-in endpoint\n",
590 			USBDEVNAME(sc->sc_dev));
591 		goto bad;
592 	}
593 	if (sc->sc_isoc_out_ep == -1) {
594 		printf("%s: Could not detect isoc-out endpoint\n",
595 			USBDEVNAME(sc->sc_dev));
596 		goto bad;
597 	}
598 	if (sc->sc_isoc_size <= 0) {
599 		printf("%s: Invalid isoc. packet size=%d\n",
600 			USBDEVNAME(sc->sc_dev), sc->sc_isoc_size);
601 		goto bad;
602 	}
603 
604 	error = usbd_set_interface(sc->sc_iface1, alt_no);
605 	if (error) {
606 		printf("%s: Could not set alternate configuration " \
607 			"%d for interface 1. %s (%d)\n", USBDEVNAME(sc->sc_dev),
608 			alt_no, usbd_errstr(error), error);
609 		goto bad;
610 	}
611 
612 	/* Allocate USB transfer handles and buffers */
613 	sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
614 	if (sc->sc_ctrl_xfer == NULL) {
615 		printf("%s: Could not allocate control xfer handle\n",
616 			USBDEVNAME(sc->sc_dev));
617 		goto bad;
618 	}
619 	sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
620 						UBT_CTRL_BUFFER_SIZE);
621 	if (sc->sc_ctrl_buffer == NULL) {
622 		printf("%s: Could not allocate control buffer\n",
623 			USBDEVNAME(sc->sc_dev));
624 		goto bad;
625 	}
626 
627 	sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
628 	if (sc->sc_intr_xfer == NULL) {
629 		printf("%s: Could not allocate interrupt xfer handle\n",
630 			USBDEVNAME(sc->sc_dev));
631 		goto bad;
632 	}
633 
634 	sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
635 	if (sc->sc_bulk_in_xfer == NULL) {
636 		printf("%s: Could not allocate bulk-in xfer handle\n",
637 			USBDEVNAME(sc->sc_dev));
638 		goto bad;
639 	}
640 
641 	sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
642 	if (sc->sc_bulk_out_xfer == NULL) {
643 		printf("%s: Could not allocate bulk-out xfer handle\n",
644 			USBDEVNAME(sc->sc_dev));
645 		goto bad;
646 	}
647 	sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
648 						UBT_BULK_BUFFER_SIZE);
649 	if (sc->sc_bulk_out_buffer == NULL) {
650 		printf("%s: Could not allocate bulk-out buffer\n",
651 			USBDEVNAME(sc->sc_dev));
652 		goto bad;
653 	}
654 
655 	/*
656 	 * Allocate buffers for isoc. transfers
657 	 */
658 
659 	sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
660 
661 	sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
662 	if (sc->sc_isoc_in_xfer == NULL) {
663 		printf("%s: Could not allocate isoc-in xfer handle\n",
664 			USBDEVNAME(sc->sc_dev));
665 		goto bad;
666 	}
667 	sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
668 					sc->sc_isoc_nframes * sc->sc_isoc_size);
669 	if (sc->sc_isoc_in_buffer == NULL) {
670 		printf("%s: Could not allocate isoc-in buffer\n",
671 			USBDEVNAME(sc->sc_dev));
672 		goto bad;
673 	}
674 	sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
675 						M_USBDEV, M_NOWAIT);
676 	if (sc->sc_isoc_in_frlen == NULL) {
677 		printf("%s: Could not allocate isoc-in frame sizes buffer\n",
678 			USBDEVNAME(sc->sc_dev));
679 		goto bad;
680 	}
681 
682 	sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
683 	if (sc->sc_isoc_out_xfer == NULL) {
684 		printf("%s: Could not allocate isoc-out xfer handle\n",
685 			USBDEVNAME(sc->sc_dev));
686 		goto bad;
687 	}
688 	sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
689 					sc->sc_isoc_nframes * sc->sc_isoc_size);
690 	if (sc->sc_isoc_out_buffer == NULL) {
691 		printf("%s: Could not allocate isoc-out buffer\n",
692 			USBDEVNAME(sc->sc_dev));
693 		goto bad;
694 	}
695 	sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
696 						M_USBDEV, M_NOWAIT);
697 	if (sc->sc_isoc_out_frlen == NULL) {
698 		printf("%s: Could not allocate isoc-out frame sizes buffer\n",
699 			USBDEVNAME(sc->sc_dev));
700 		goto bad;
701 	}
702 
703 	printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
704 		"isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
705 		USBDEVNAME(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
706 		sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes,
707 		(sc->sc_isoc_nframes * sc->sc_isoc_size));
708 
709 	/*
710 	 * Open pipes
711 	 */
712 
713 	/* Interrupt */
714 	error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
715 			USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
716 	if (error != USBD_NORMAL_COMPLETION) {
717 		printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
718 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
719 			error);
720 		goto bad;
721 	}
722 
723 	/* Bulk-in */
724 	error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
725 			USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
726 	if (error != USBD_NORMAL_COMPLETION) {
727 		printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
728 			__func__,  USBDEVNAME(sc->sc_dev), usbd_errstr(error),
729 			error);
730 		goto bad;
731 	}
732 
733 	/* Bulk-out */
734 	error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
735 			USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
736 	if (error != USBD_NORMAL_COMPLETION) {
737 		printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
738 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
739 			error);
740 		goto bad;
741 	}
742 
743 #if __broken__ /* XXX FIXME */
744 	/* Isoc-in */
745 	error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
746 			USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
747 	if (error != USBD_NORMAL_COMPLETION) {
748 		printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
749 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
750 			error);
751 		goto bad;
752 	}
753 
754 	/* Isoc-out */
755 	error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
756 			USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
757 	if (error != USBD_NORMAL_COMPLETION) {
758 		printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
759 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
760 			error);
761 		goto bad;
762 	}
763 #endif /* __broken__ */
764 
765 	/* Create Netgraph node */
766 	if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
767 		printf("%s: Could not create Netgraph node\n",
768 			USBDEVNAME(sc->sc_dev));
769 		sc->sc_node = NULL;
770 		goto bad;
771 	}
772 
773 	/* Name node */
774 	if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
775 		printf("%s: Could not name Netgraph node\n",
776 			USBDEVNAME(sc->sc_dev));
777 		NG_NODE_UNREF(sc->sc_node);
778 		sc->sc_node = NULL;
779 		goto bad;
780 	}
781 
782 	NG_NODE_SET_PRIVATE(sc->sc_node, sc);
783 	NG_NODE_FORCE_WRITER(sc->sc_node);
784 
785 	/* Claim all interfaces on the device */
786 	for (i = 0; i < uaa->nifaces; i++)
787 		uaa->ifaces[i] = NULL;
788 
789 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
790 		USBDEV(sc->sc_dev));
791 
792 	USB_ATTACH_SUCCESS_RETURN;
793 bad:
794 	ubt_detach(self);
795 
796 	USB_ATTACH_ERROR_RETURN;
797 } /* USB_ATTACH(ubt) */
798 
799 /*
800  * Detach the device
801  */
802 
803 USB_DETACH(ubt)
804 {
805 	USB_DETACH_START(ubt, sc);
806 
807 	sc->sc_dying = 1;
808 
809 	ubt_destroy_device_nodes(sc); /* XXX FIXME locking? */
810 
811 	/* Destroy Netgraph node */
812 	if (sc->sc_node != NULL) {
813 		NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
814 		ng_rmnode_self(sc->sc_node);
815 		sc->sc_node = NULL;
816 	}
817 
818 	/* Close pipes */
819 	if (sc->sc_intr_pipe != NULL) {
820 		usbd_close_pipe(sc->sc_intr_pipe);
821 		sc->sc_intr_pipe = NULL;
822 	}
823 
824 	if (sc->sc_bulk_in_pipe != NULL) {
825 		usbd_close_pipe(sc->sc_bulk_in_pipe);
826 		sc->sc_bulk_in_pipe = NULL;
827 	}
828 	if (sc->sc_bulk_out_pipe != NULL) {
829 		usbd_close_pipe(sc->sc_bulk_out_pipe);
830 		sc->sc_bulk_out_pipe = NULL;
831 	}
832 
833 	if (sc->sc_isoc_in_pipe != NULL) {
834 		usbd_close_pipe(sc->sc_isoc_in_pipe);
835 		sc->sc_isoc_in_pipe = NULL;
836 	}
837 	if (sc->sc_isoc_out_pipe != NULL) {
838 		usbd_close_pipe(sc->sc_isoc_out_pipe);
839 		sc->sc_isoc_out_pipe = NULL;
840 	}
841 
842 	/* Destroy USB transfer handles */
843 	if (sc->sc_ctrl_xfer != NULL) {
844 		usbd_free_xfer(sc->sc_ctrl_xfer);
845 		sc->sc_ctrl_xfer = NULL;
846 	}
847 
848 	if (sc->sc_intr_xfer != NULL) {
849 		usbd_free_xfer(sc->sc_intr_xfer);
850 		sc->sc_intr_xfer = NULL;
851 	}
852 
853 	if (sc->sc_bulk_in_xfer != NULL) {
854 		usbd_free_xfer(sc->sc_bulk_in_xfer);
855 		sc->sc_bulk_in_xfer = NULL;
856 	}
857 	if (sc->sc_bulk_out_xfer != NULL) {
858 		usbd_free_xfer(sc->sc_bulk_out_xfer);
859 		sc->sc_bulk_out_xfer = NULL;
860 	}
861 
862 	if (sc->sc_isoc_in_xfer != NULL) {
863 		usbd_free_xfer(sc->sc_isoc_in_xfer);
864 		sc->sc_isoc_in_xfer = NULL;
865 	}
866 	if (sc->sc_isoc_out_xfer != NULL) {
867 		usbd_free_xfer(sc->sc_isoc_out_xfer);
868 		sc->sc_isoc_out_xfer = NULL;
869 	}
870 
871 	/* Destroy isoc. frame size buffers */
872 	if (sc->sc_isoc_in_frlen != NULL) {
873 		free(sc->sc_isoc_in_frlen, M_USBDEV);
874 		sc->sc_isoc_in_frlen = NULL;
875 	}
876 	if (sc->sc_isoc_out_frlen != NULL) {
877 		free(sc->sc_isoc_out_frlen, M_USBDEV);
878 		sc->sc_isoc_out_frlen = NULL;
879 	}
880 
881 	/* Destroy queues */
882 	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
883 	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
884 	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
885 
886 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
887 			USBDEV(sc->sc_dev));
888 
889 	return (0);
890 } /* USB_DETACH(ubt) */
891 
892 /*
893  * Start USB control request (HCI command). Must be called with node locked
894  */
895 
896 Static usbd_status
897 ubt_request_start(ubt_softc_p sc)
898 {
899 	usb_device_request_t	 req;
900 	struct mbuf		*m = NULL;
901 	usbd_status		 status;
902 
903 	KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
904 "%s: %s - Another control request is pending\n",
905 		__func__, USBDEVNAME(sc->sc_dev)));
906 
907 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
908 	if (m == NULL) {
909 		NG_UBT_INFO(
910 "%s: %s - HCI command queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
911 
912 		return (USBD_NORMAL_COMPLETION);
913 	}
914 
915 	/*
916 	 * Check HCI command frame size and copy it back to
917 	 * linear USB transfer buffer.
918 	 */
919 
920 	if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
921 		panic(
922 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
923 			__func__, USBDEVNAME(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
924 			m->m_pkthdr.len);
925 
926 	m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
927 
928 	/* Initialize a USB control request and then schedule it */
929 	bzero(&req, sizeof(req));
930 	req.bmRequestType = UBT_HCI_REQUEST;
931 	USETW(req.wLength, m->m_pkthdr.len);
932 
933 	NG_UBT_INFO(
934 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
935 		__func__, USBDEVNAME(sc->sc_dev), req.bmRequestType,
936 		UGETW(req.wLength));
937 
938 	usbd_setup_default_xfer(
939 		sc->sc_ctrl_xfer,
940 		sc->sc_udev,
941 		(usbd_private_handle) sc->sc_node,
942 		USBD_DEFAULT_TIMEOUT, /* XXX */
943 		&req,
944 		sc->sc_ctrl_buffer,
945 		m->m_pkthdr.len,
946 		USBD_NO_COPY,
947 		ubt_request_complete);
948 
949 	NG_NODE_REF(sc->sc_node);
950 
951 	status = usbd_transfer(sc->sc_ctrl_xfer);
952 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
953 		NG_UBT_ERR(
954 "%s: %s - Could not start control request. %s (%d)\n",
955 			__func__, USBDEVNAME(sc->sc_dev),
956 			usbd_errstr(status), status);
957 
958 		NG_NODE_UNREF(sc->sc_node);
959 
960 		NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
961 		NG_UBT_STAT_OERROR(sc->sc_stat);
962 
963 		/* XXX FIXME should we try to resubmit another request? */
964 	} else {
965 		NG_UBT_INFO(
966 "%s: %s - Control request has been started\n",
967 			__func__, USBDEVNAME(sc->sc_dev));
968 
969 		sc->sc_flags |= UBT_CMD_XMIT;
970 		status = USBD_NORMAL_COMPLETION;
971 	}
972 
973 	NG_FREE_M(m);
974 
975 	return (status);
976 } /* ubt_request_start */
977 
978 /*
979  * USB control request callback
980  */
981 
982 Static void
983 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
984 {
985 	ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
986 	NG_NODE_UNREF((node_p) p);
987 } /* ubt_request_complete */
988 
989 Static void
990 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
991 {
992 	ubt_softc_p		sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
993 	usbd_xfer_handle	h = (usbd_xfer_handle) arg1;
994 	usbd_status		s = (usbd_status) arg2;
995 
996 	if (sc == NULL)
997 		return;
998 
999 	KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
1000 "%s: %s - No control request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1001 
1002 	sc->sc_flags &= ~UBT_CMD_XMIT;
1003 
1004 	if (s == USBD_CANCELLED) {
1005 		NG_UBT_INFO(
1006 "%s: %s - Control request cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
1007 
1008 		return;
1009 	}
1010 
1011 	if (s != USBD_NORMAL_COMPLETION) {
1012 		NG_UBT_ERR(
1013 "%s: %s - Control request failed. %s (%d)\n",
1014 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1015 
1016 		if (s == USBD_STALLED)
1017 			usbd_clear_endpoint_stall_async(h->pipe);
1018 
1019 		NG_UBT_STAT_OERROR(sc->sc_stat);
1020 	} else {
1021 		NG_UBT_INFO(
1022 "%s: %s - Sent %d bytes to control pipe\n",
1023 			__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1024 
1025 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1026 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1027 	}
1028 
1029 	if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
1030 		ubt_request_start(sc);
1031 } /* ubt_request_complete2 */
1032 
1033 /*
1034  * Start interrupt transfer. Must be called when node is locked
1035  */
1036 
1037 Static usbd_status
1038 ubt_intr_start(ubt_softc_p sc)
1039 {
1040 	struct mbuf	*m = NULL;
1041 	usbd_status	 status;
1042 
1043 	KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
1044 "%s: %s - Another interrupt request is pending\n",
1045 		__func__, USBDEVNAME(sc->sc_dev)));
1046 
1047 	/* Allocate new mbuf cluster */
1048 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1049 	if (m == NULL)
1050 		return (USBD_NOMEM);
1051 
1052 	MCLGET(m, M_DONTWAIT);
1053 	if (!(m->m_flags & M_EXT)) {
1054 		NG_FREE_M(m);
1055 		return (USBD_NOMEM);
1056 	}
1057 
1058 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1059 		*mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
1060 		m->m_pkthdr.len = m->m_len = 1;
1061 	} else
1062 		m->m_pkthdr.len = m->m_len = 0;
1063 
1064 	/* Initialize a USB transfer and then schedule it */
1065 	usbd_setup_xfer(
1066 			sc->sc_intr_xfer,
1067 			sc->sc_intr_pipe,
1068 			(usbd_private_handle) sc->sc_node,
1069 			(void *)(mtod(m, u_int8_t *) + m->m_len),
1070 			MCLBYTES - m->m_len,
1071 			USBD_SHORT_XFER_OK,
1072 			USBD_NO_TIMEOUT,
1073 			ubt_intr_complete);
1074 
1075 	NG_NODE_REF(sc->sc_node);
1076 
1077 	status = usbd_transfer(sc->sc_intr_xfer);
1078 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1079 		NG_UBT_ERR(
1080 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1081 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1082 			status);
1083 
1084 		NG_NODE_UNREF(sc->sc_node);
1085 
1086 		NG_FREE_M(m);
1087 
1088 		return (status);
1089 	}
1090 
1091 	sc->sc_flags |= UBT_EVT_RECV;
1092 	sc->sc_intr_buffer = m;
1093 
1094 	return (USBD_NORMAL_COMPLETION);
1095 } /* ubt_intr_start */
1096 
1097 /*
1098  * Process interrupt from USB device (We got data from interrupt pipe)
1099  */
1100 
1101 Static void
1102 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1103 {
1104 	ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1105 	NG_NODE_UNREF((node_p) p);
1106 } /* ubt_intr_complete */
1107 
1108 Static void
1109 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1110 {
1111 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1112 	usbd_xfer_handle	 h = (usbd_xfer_handle) arg1;
1113 	usbd_status		 s = (usbd_status) arg2;
1114 	struct mbuf		*m = NULL;
1115 	ng_hci_event_pkt_t	*hdr = NULL;
1116 	int			 error;
1117 
1118 	if (sc == NULL)
1119 		return;
1120 
1121 	KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1122 "%s: %s - No interrupt request is pending\n",
1123 		__func__, USBDEVNAME(sc->sc_dev)));
1124 
1125 	sc->sc_flags &= ~UBT_EVT_RECV;
1126 
1127 	m = sc->sc_intr_buffer;
1128 	sc->sc_intr_buffer = NULL;
1129 
1130 	hdr = mtod(m, ng_hci_event_pkt_t *);
1131 
1132 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1133 		NG_UBT_INFO(
1134 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1135 
1136 		NG_FREE_M(m);
1137 		return;
1138 	}
1139 
1140 	if (s == USBD_CANCELLED) {
1141 		NG_UBT_INFO(
1142 "%s: %s - Interrupt xfer cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
1143 
1144 		NG_FREE_M(m);
1145 		return;
1146 	}
1147 
1148 	if (s != USBD_NORMAL_COMPLETION) {
1149 		NG_UBT_WARN(
1150 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1151 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1152 
1153 		if (s == USBD_STALLED)
1154 			usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1155 
1156 		NG_UBT_STAT_IERROR(sc->sc_stat);
1157 		NG_FREE_M(m);
1158 
1159 		return; /* XXX FIXME we should restart after some delay */
1160 	}
1161 
1162 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1163 	m->m_pkthdr.len += h->actlen;
1164 	m->m_len += h->actlen;
1165 
1166 	NG_UBT_INFO(
1167 "%s: %s - Got %d bytes from interrupt pipe\n",
1168 		__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1169 
1170 	if (m->m_pkthdr.len < sizeof(*hdr)) {
1171 		NG_FREE_M(m);
1172 		goto done;
1173 	}
1174 
1175 	if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1176 		NG_UBT_INFO(
1177 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1178 			__func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1179 			hdr->length);
1180 
1181 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1182 
1183 		NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1184 		if (error != 0)
1185 			NG_UBT_STAT_IERROR(sc->sc_stat);
1186 	} else {
1187 		NG_UBT_ERR(
1188 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1189 			__func__, USBDEVNAME(sc->sc_dev), hdr->length,
1190 			m->m_pkthdr.len);
1191 
1192 		NG_UBT_STAT_IERROR(sc->sc_stat);
1193 		NG_FREE_M(m);
1194 	}
1195 done:
1196 	ubt_intr_start(sc);
1197 } /* ubt_intr_complete2 */
1198 
1199 /*
1200  * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1201  */
1202 
1203 Static usbd_status
1204 ubt_bulk_in_start(ubt_softc_p sc)
1205 {
1206 	struct mbuf	*m = NULL;
1207 	usbd_status	 status;
1208 
1209 	KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1210 "%s: %s - Another bulk-in request is pending\n",
1211 		__func__, USBDEVNAME(sc->sc_dev)));
1212 
1213 	/* Allocate new mbuf cluster */
1214 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1215 	if (m == NULL)
1216 		return (USBD_NOMEM);
1217 
1218 	MCLGET(m, M_DONTWAIT);
1219 	if (!(m->m_flags & M_EXT)) {
1220 		NG_FREE_M(m);
1221 		return (USBD_NOMEM);
1222 	}
1223 
1224 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1225 		*mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1226 		m->m_pkthdr.len = m->m_len = 1;
1227 	} else
1228 		m->m_pkthdr.len = m->m_len = 0;
1229 
1230 	/* Initialize a bulk-in USB transfer and then schedule it */
1231 	usbd_setup_xfer(
1232 			sc->sc_bulk_in_xfer,
1233 			sc->sc_bulk_in_pipe,
1234 			(usbd_private_handle) sc->sc_node,
1235 			(void *)(mtod(m, u_int8_t *) + m->m_len),
1236 			MCLBYTES - m->m_len,
1237 			USBD_SHORT_XFER_OK,
1238 			USBD_NO_TIMEOUT,
1239 			ubt_bulk_in_complete);
1240 
1241 	NG_NODE_REF(sc->sc_node);
1242 
1243 	status = usbd_transfer(sc->sc_bulk_in_xfer);
1244 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1245 		NG_UBT_ERR(
1246 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1247 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1248 			status);
1249 
1250 		NG_NODE_UNREF(sc->sc_node);
1251 
1252 		NG_FREE_M(m);
1253 
1254 		return (status);
1255 	}
1256 
1257 	sc->sc_flags |= UBT_ACL_RECV;
1258 	sc->sc_bulk_in_buffer = m;
1259 
1260 	return (USBD_NORMAL_COMPLETION);
1261 } /* ubt_bulk_in_start */
1262 
1263 /*
1264  * USB bulk-in transfer callback
1265  */
1266 
1267 Static void
1268 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1269 {
1270 	ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1271 	NG_NODE_UNREF((node_p) p);
1272 } /* ubt_bulk_in_complete */
1273 
1274 Static void
1275 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1276 {
1277 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1278 	usbd_xfer_handle	 h = (usbd_xfer_handle) arg1;
1279 	usbd_status		 s = (usbd_status) arg2;
1280 	struct mbuf		*m = NULL;
1281 	ng_hci_acldata_pkt_t	*hdr = NULL;
1282 	int			 len;
1283 
1284 	if (sc == NULL)
1285 		return;
1286 
1287 	KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1288 "%s: %s - No bulk-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1289 
1290 	sc->sc_flags &= ~UBT_ACL_RECV;
1291 
1292 	m = sc->sc_bulk_in_buffer;
1293 	sc->sc_bulk_in_buffer = NULL;
1294 
1295 	hdr = mtod(m, ng_hci_acldata_pkt_t *);
1296 
1297 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1298 		NG_UBT_INFO(
1299 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1300 
1301 		NG_FREE_M(m);
1302 		return;
1303 	}
1304 
1305 	if (s == USBD_CANCELLED) {
1306 		NG_UBT_INFO(
1307 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1308 			__func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_in_pipe);
1309 
1310 		NG_FREE_M(m);
1311 		return;
1312 	}
1313 
1314 	if (s != USBD_NORMAL_COMPLETION) {
1315 		NG_UBT_WARN(
1316 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1317 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1318 
1319 		if (s == USBD_STALLED)
1320 			usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1321 
1322 		NG_UBT_STAT_IERROR(sc->sc_stat);
1323 		NG_FREE_M(m);
1324 
1325 		return; /* XXX FIXME we should restart after some delay */
1326 	}
1327 
1328 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1329 	m->m_pkthdr.len += h->actlen;
1330 	m->m_len += h->actlen;
1331 
1332 	NG_UBT_INFO(
1333 "%s: %s - Got %d bytes from bulk-in pipe\n",
1334 		__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1335 
1336 	if (m->m_pkthdr.len < sizeof(*hdr)) {
1337 		NG_FREE_M(m);
1338 		goto done;
1339 	}
1340 
1341 	len = le16toh(hdr->length);
1342 	if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1343 		NG_UBT_INFO(
1344 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1345 			__func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, len);
1346 
1347 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1348 
1349 		NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1350 		if (len != 0)
1351 			NG_UBT_STAT_IERROR(sc->sc_stat);
1352 	} else {
1353 		NG_UBT_ERR(
1354 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1355 			__func__, USBDEVNAME(sc->sc_dev), len,
1356 			m->m_pkthdr.len);
1357 
1358 		NG_UBT_STAT_IERROR(sc->sc_stat);
1359 		NG_FREE_M(m);
1360 	}
1361 done:
1362 	ubt_bulk_in_start(sc);
1363 } /* ubt_bulk_in_complete2 */
1364 
1365 /*
1366  * Start bulk-out USB transfer. Must be called with node locked
1367  */
1368 
1369 Static usbd_status
1370 ubt_bulk_out_start(ubt_softc_p sc)
1371 {
1372 	struct mbuf	*m = NULL;
1373 	usbd_status	status;
1374 
1375 	KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1376 "%s: %s - Another bulk-out request is pending\n",
1377 		__func__, USBDEVNAME(sc->sc_dev)));
1378 
1379 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1380 	if (m == NULL) {
1381 		NG_UBT_INFO(
1382 "%s: %s - ACL data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1383 
1384  		return (USBD_NORMAL_COMPLETION);
1385 	}
1386 
1387 	/*
1388 	 * Check ACL data frame size and copy it back to linear USB
1389 	 * transfer buffer.
1390 	 */
1391 
1392 	if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1393 		panic(
1394 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1395 			__func__, USBDEVNAME(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1396 			m->m_pkthdr.len);
1397 
1398 	m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1399 
1400 	/* Initialize a bulk-out USB transfer and then schedule it */
1401 	usbd_setup_xfer(
1402 			sc->sc_bulk_out_xfer,
1403 			sc->sc_bulk_out_pipe,
1404 			(usbd_private_handle) sc->sc_node,
1405 			sc->sc_bulk_out_buffer,
1406 			m->m_pkthdr.len,
1407 			USBD_NO_COPY,
1408 			USBD_DEFAULT_TIMEOUT, /* XXX */
1409 			ubt_bulk_out_complete);
1410 
1411 	NG_NODE_REF(sc->sc_node);
1412 
1413 	status = usbd_transfer(sc->sc_bulk_out_xfer);
1414 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1415 		NG_UBT_ERR(
1416 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1417 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1418 			status);
1419 
1420 		NG_NODE_UNREF(sc->sc_node);
1421 
1422 		NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1423 		NG_UBT_STAT_OERROR(sc->sc_stat);
1424 
1425 		/* XXX FIXME should we try to start another transfer? */
1426 	} else {
1427 		NG_UBT_INFO(
1428 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1429 			__func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len);
1430 
1431 		sc->sc_flags |= UBT_ACL_XMIT;
1432 		status = USBD_NORMAL_COMPLETION;
1433 	}
1434 
1435 	NG_FREE_M(m);
1436 
1437 	return (status);
1438 } /* ubt_bulk_out_start */
1439 
1440 /*
1441  * USB bulk-out transfer callback
1442  */
1443 
1444 Static void
1445 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1446 {
1447 	ng_send_fn((node_p) p,  NULL, ubt_bulk_out_complete2, (void *) h, s);
1448 	NG_NODE_UNREF((node_p) p);
1449 } /* ubt_bulk_out_complete */
1450 
1451 Static void
1452 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1453 {
1454 	ubt_softc_p		sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1455 	usbd_xfer_handle	h = (usbd_xfer_handle) arg1;
1456 	usbd_status		s = (usbd_status) arg2;
1457 
1458 	if (sc == NULL)
1459 		return;
1460 
1461 	KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1462 "%s: %s - No bulk-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1463 
1464 	sc->sc_flags &= ~UBT_ACL_XMIT;
1465 
1466 	if (s == USBD_CANCELLED) {
1467 		NG_UBT_INFO(
1468 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1469 			__func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_out_pipe);
1470 
1471 		return;
1472 	}
1473 
1474 	if (s != USBD_NORMAL_COMPLETION) {
1475 		NG_UBT_WARN(
1476 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1477 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1478 
1479 		if (s == USBD_STALLED)
1480 			usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1481 
1482 		NG_UBT_STAT_OERROR(sc->sc_stat);
1483 	} else {
1484 		NG_UBT_INFO(
1485 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1486 			__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1487 
1488 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1489 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1490 	}
1491 
1492 	if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1493 		ubt_bulk_out_start(sc);
1494 } /* ubt_bulk_out_complete2 */
1495 
1496 /*
1497  * Start Isochronous-in USB transfer. Must be called with node locked
1498  */
1499 
1500 Static usbd_status
1501 ubt_isoc_in_start(ubt_softc_p sc)
1502 {
1503 	usbd_status	status;
1504 	int		i;
1505 
1506 	KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1507 "%s: %s - Another isoc-in request is pending\n",
1508                 __func__, USBDEVNAME(sc->sc_dev)));
1509 
1510 	/* Initialize a isoc-in USB transfer and then schedule it */
1511 	for (i = 0; i < sc->sc_isoc_nframes; i++)
1512 		sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1513 
1514 	usbd_setup_isoc_xfer(
1515 			sc->sc_isoc_in_xfer,
1516 			sc->sc_isoc_in_pipe,
1517 			(usbd_private_handle) sc->sc_node,
1518 			sc->sc_isoc_in_frlen,
1519 			sc->sc_isoc_nframes,
1520 			USBD_NO_COPY, /* XXX flags */
1521 			ubt_isoc_in_complete);
1522 
1523 	NG_NODE_REF(sc->sc_node);
1524 
1525 	status = usbd_transfer(sc->sc_isoc_in_xfer);
1526 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1527 		NG_UBT_ERR(
1528 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1529 			__func__, USBDEVNAME(sc->sc_dev),
1530 			usbd_errstr(status), status);
1531 
1532 		NG_NODE_UNREF(sc->sc_node);
1533 
1534 		return (status);
1535 	}
1536 
1537 	sc->sc_flags |= UBT_SCO_RECV;
1538 
1539 	return (USBD_NORMAL_COMPLETION);
1540 } /* ubt_isoc_in_start */
1541 
1542 /*
1543  * USB isochronous transfer callback
1544  */
1545 
1546 Static void
1547 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1548 {
1549 	ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1550 	NG_NODE_UNREF((node_p) p);
1551 } /* ubt_isoc_in_complete */
1552 
1553 Static void
1554 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1555 {
1556 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1557 	usbd_xfer_handle	 h = (usbd_xfer_handle) arg1;
1558 	usbd_status		 s = (usbd_status) arg2;
1559 	struct mbuf		*m = NULL;
1560 	ng_hci_scodata_pkt_t	*hdr = NULL;
1561 	u_int8_t		*b = NULL;
1562 	int			 i;
1563 
1564 	if (sc == NULL)
1565 		return;
1566 
1567 	KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1568 "%s: %s - No isoc-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1569 
1570 	sc->sc_flags &= ~UBT_SCO_RECV;
1571 
1572 	if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1573 		NG_UBT_INFO(
1574 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1575 
1576 		return;
1577 	}
1578 
1579 	if (s == USBD_CANCELLED) {
1580 		NG_UBT_INFO(
1581 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1582 			__func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_in_pipe);
1583 
1584 		return;
1585 	}
1586 
1587 	if (s != USBD_NORMAL_COMPLETION) {
1588 		NG_UBT_WARN(
1589 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1590 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1591 
1592 		if (s == USBD_STALLED)
1593 			usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1594 
1595 		NG_UBT_STAT_IERROR(sc->sc_stat);
1596 
1597 		return; /* XXX FIXME we should restart after some delay */
1598 	}
1599 
1600 	NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1601 
1602 	NG_UBT_INFO(
1603 "%s: %s - Got %d bytes from isoc-in pipe\n",
1604 		__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1605 
1606 	/* Copy SCO data frame to mbuf */
1607 	MGETHDR(m, M_DONTWAIT, MT_DATA);
1608 	if (m == NULL) {
1609 		NG_UBT_ALERT(
1610 "%s: %s - Could not allocate mbuf\n",
1611 			__func__, USBDEVNAME(sc->sc_dev));
1612 
1613 		NG_UBT_STAT_IERROR(sc->sc_stat);
1614 		goto done;
1615 	}
1616 
1617 	/* Fix SCO data frame header if required */
1618 	if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1619 		*mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1620 		m->m_pkthdr.len = 1;
1621 		m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1622 	} else {
1623 		m->m_pkthdr.len = 0;
1624 		m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1625 	}
1626 
1627 	/*
1628 	 * XXX FIXME how do we know how many frames we have received?
1629 	 * XXX use frlen for now. is that correct?
1630 	 */
1631 
1632 	b = (u_int8_t *) sc->sc_isoc_in_buffer;
1633 
1634 	for (i = 0; i < sc->sc_isoc_nframes; i++) {
1635 		b += (i * sc->sc_isoc_size);
1636 
1637 		if (sc->sc_isoc_in_frlen[i] > 0)
1638 			m_copyback(m, m->m_pkthdr.len,
1639 				sc->sc_isoc_in_frlen[i], b);
1640 	}
1641 
1642 	if (m->m_pkthdr.len < sizeof(*hdr))
1643 		goto done;
1644 
1645 	hdr = mtod(m, ng_hci_scodata_pkt_t *);
1646 
1647 	if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1648 		NG_UBT_INFO(
1649 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1650 			__func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1651 			hdr->length);
1652 
1653 		NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1654 
1655 		NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1656 		if (i != 0)
1657 			NG_UBT_STAT_IERROR(sc->sc_stat);
1658 	} else {
1659 		NG_UBT_ERR(
1660 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1661 			__func__, USBDEVNAME(sc->sc_dev), hdr->length,
1662 			m->m_pkthdr.len);
1663 
1664 		NG_UBT_STAT_IERROR(sc->sc_stat);
1665 		NG_FREE_M(m);
1666 	}
1667 done:
1668 	ubt_isoc_in_start(sc);
1669 } /* ubt_isoc_in_complete2 */
1670 
1671 /*
1672  * Start isochronous-out USB transfer. Must be called with node locked
1673  */
1674 
1675 Static usbd_status
1676 ubt_isoc_out_start(ubt_softc_p sc)
1677 {
1678 	struct mbuf	*m = NULL;
1679 	u_int8_t	*b = NULL;
1680 	int		 i, len, nframes;
1681 	usbd_status	 status;
1682 
1683 	KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1684 "%s: %s - Another isoc-out request is pending\n",
1685 		__func__, USBDEVNAME(sc->sc_dev)));
1686 
1687 	NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1688 	if (m == NULL) {
1689 		NG_UBT_INFO(
1690 "%s: %s - SCO data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1691 
1692  		return (USBD_NORMAL_COMPLETION);
1693 	}
1694 
1695 	/* Copy entire SCO frame into USB transfer buffer and start transfer */
1696 	b = (u_int8_t *) sc->sc_isoc_out_buffer;
1697 	nframes = 0;
1698 
1699 	for (i = 0; i < sc->sc_isoc_nframes; i++) {
1700 		b += (i * sc->sc_isoc_size);
1701 
1702 		len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1703 		if (len > 0) {
1704 			m_copydata(m, 0, len, b);
1705 			m_adj(m, len);
1706 			nframes ++;
1707 		}
1708 
1709 		sc->sc_isoc_out_frlen[i] = len;
1710 	}
1711 
1712 	if (m->m_pkthdr.len > 0)
1713 		panic(
1714 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1715 			__func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_nframes,
1716 			sc->sc_isoc_size, m->m_pkthdr.len);
1717 
1718 	NG_FREE_M(m);
1719 
1720 	/* Initialize a isoc-out USB transfer and then schedule it */
1721 	usbd_setup_isoc_xfer(
1722 			sc->sc_isoc_out_xfer,
1723 			sc->sc_isoc_out_pipe,
1724 			(usbd_private_handle) sc->sc_node,
1725 			sc->sc_isoc_out_frlen,
1726 			nframes,
1727 			USBD_NO_COPY,
1728 			ubt_isoc_out_complete);
1729 
1730 	NG_NODE_REF(sc->sc_node);
1731 
1732 	status = usbd_transfer(sc->sc_isoc_out_xfer);
1733 	if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1734 		NG_UBT_ERR(
1735 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1736 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1737 			status);
1738 
1739 		NG_NODE_UNREF(sc->sc_node);
1740 
1741 		NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1742 		NG_UBT_STAT_OERROR(sc->sc_stat);
1743 	} else {
1744 		NG_UBT_INFO(
1745 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1746 			__func__, USBDEVNAME(sc->sc_dev), nframes,
1747 			sc->sc_isoc_size);
1748 
1749 		sc->sc_flags |= UBT_SCO_XMIT;
1750 		status = USBD_NORMAL_COMPLETION;
1751 	}
1752 
1753 	return (status);
1754 } /* ubt_isoc_out_start */
1755 
1756 /*
1757  * USB isoc-out. transfer callback
1758  */
1759 
1760 Static void
1761 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1762 {
1763 	ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1764 	NG_NODE_UNREF((node_p) p);
1765 } /* ubt_isoc_out_complete */
1766 
1767 Static void
1768 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1769 {
1770 	ubt_softc_p		sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1771 	usbd_xfer_handle	h = (usbd_xfer_handle) arg1;
1772 	usbd_status		s = (usbd_status) arg2;
1773 
1774 	if (sc == NULL)
1775 		return;
1776 
1777 	KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1778 "%s: %s - No isoc-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1779 
1780 	sc->sc_flags &= ~UBT_SCO_XMIT;
1781 
1782 	if (s == USBD_CANCELLED) {
1783 		NG_UBT_INFO(
1784 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1785 			__func__, USBDEVNAME(sc->sc_dev),
1786 			sc->sc_isoc_out_pipe);
1787 
1788 		return;
1789 	}
1790 
1791 	if (s != USBD_NORMAL_COMPLETION) {
1792 		NG_UBT_WARN(
1793 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1794 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1795 
1796 		if (s == USBD_STALLED)
1797 			usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1798 
1799 		NG_UBT_STAT_OERROR(sc->sc_stat);
1800 	} else {
1801 		NG_UBT_INFO(
1802 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1803 			__func__, USBDEVNAME(sc->sc_dev), h->actlen);
1804 
1805 		NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1806 		NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1807 	}
1808 
1809 	if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1810 		ubt_isoc_out_start(sc);
1811 } /* ubt_isoc_out_complete2 */
1812 
1813 /*
1814  * Abort transfers on all USB pipes
1815  */
1816 
1817 Static void
1818 ubt_reset(ubt_softc_p sc)
1819 {
1820 	/* Interrupt */
1821 	if (sc->sc_intr_pipe != NULL)
1822 		usbd_abort_pipe(sc->sc_intr_pipe);
1823 
1824 	/* Bulk-in/out */
1825 	if (sc->sc_bulk_in_pipe != NULL)
1826 		usbd_abort_pipe(sc->sc_bulk_in_pipe);
1827 	if (sc->sc_bulk_out_pipe != NULL)
1828 		usbd_abort_pipe(sc->sc_bulk_out_pipe);
1829 
1830 	/* Isoc-in/out */
1831 	if (sc->sc_isoc_in_pipe != NULL)
1832 		usbd_abort_pipe(sc->sc_isoc_in_pipe);
1833 	if (sc->sc_isoc_out_pipe != NULL)
1834 		usbd_abort_pipe(sc->sc_isoc_out_pipe);
1835 
1836 	/* Cleanup queues */
1837 	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1838 	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1839 	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1840 } /* ubt_reset */
1841 
1842 /****************************************************************************
1843  ****************************************************************************
1844  **                        Netgraph specific
1845  ****************************************************************************
1846  ****************************************************************************/
1847 
1848 /*
1849  * Netgraph node constructor. Do not allow to create node of this type.
1850  */
1851 
1852 Static int
1853 ng_ubt_constructor(node_p node)
1854 {
1855 	return (EINVAL);
1856 } /* ng_ubt_constructor */
1857 
1858 /*
1859  * Netgraph node destructor. Destroy node only when device has been detached
1860  */
1861 
1862 Static int
1863 ng_ubt_shutdown(node_p node)
1864 {
1865 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1866 
1867 	/* Let old node go */
1868 	NG_NODE_SET_PRIVATE(node, NULL);
1869 	NG_NODE_UNREF(node);
1870 
1871 	if (sc == NULL)
1872 		goto done;
1873 
1874 	/* Create Netgraph node */
1875 	if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1876 		printf("%s: Could not create Netgraph node\n",
1877 			USBDEVNAME(sc->sc_dev));
1878 		sc->sc_node = NULL;
1879 		goto done;
1880 	}
1881 
1882 	/* Name node */
1883 	if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
1884 		printf("%s: Could not name Netgraph node\n",
1885 			USBDEVNAME(sc->sc_dev));
1886 		NG_NODE_UNREF(sc->sc_node);
1887 		sc->sc_node = NULL;
1888 		goto done;
1889 	}
1890 
1891 	NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1892 	NG_NODE_FORCE_WRITER(sc->sc_node);
1893 done:
1894 	return (0);
1895 } /* ng_ubt_shutdown */
1896 
1897 /*
1898  * Create new hook. There can only be one.
1899  */
1900 
1901 Static int
1902 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1903 {
1904 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1905 
1906 	/* Refuse to create new hook if device interface is active */
1907 	if (sc->sc_ctrl_dev != NULL || sc->sc_intr_dev != NULL ||
1908 	    sc->sc_bulk_dev != NULL)
1909 		return (EBUSY);
1910 
1911 	if (strcmp(name, NG_UBT_HOOK) != 0)
1912 		return (EINVAL);
1913 
1914 	if (sc->sc_hook != NULL)
1915 		return (EISCONN);
1916 
1917 	sc->sc_hook = hook;
1918 
1919 	return (0);
1920 } /* ng_ubt_newhook */
1921 
1922 /*
1923  * Connect hook. Start incoming USB transfers
1924  */
1925 
1926 Static int
1927 ng_ubt_connect(hook_p hook)
1928 {
1929 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1930 	usbd_status	status;
1931 
1932 	/* Refuse to connect hook if device interface is active */
1933 	if (sc->sc_ctrl_dev != NULL || sc->sc_intr_dev != NULL ||
1934 	    sc->sc_bulk_dev != NULL)
1935 		return (EBUSY);
1936 
1937 	NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1938 
1939 	/* Start intr transfer */
1940 	status = ubt_intr_start(sc);
1941 	if (status != USBD_NORMAL_COMPLETION) {
1942 		NG_UBT_ALERT(
1943 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
1944 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1945 			status);
1946 		goto fail;
1947 	}
1948 
1949 	/* Start bulk-in transfer */
1950 	status = ubt_bulk_in_start(sc);
1951 	if (status != USBD_NORMAL_COMPLETION) {
1952 		NG_UBT_ALERT(
1953 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
1954 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1955 			status);
1956 		goto fail;
1957 	}
1958 
1959 #if __broken__ /* XXX FIXME */
1960 	/* Start isoc-in transfer */
1961 	status = ubt_isoc_in_start(sc);
1962 	if (status != USBD_NORMAL_COMPLETION) {
1963 		NG_UBT_ALERT(
1964 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
1965 			__func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1966 			status);
1967 		goto fail;
1968 	}
1969 #endif /* __broken__ */
1970 
1971 	return (0);
1972 fail:
1973 	ubt_reset(sc);
1974 	sc->sc_hook = NULL;
1975 
1976 	return (ENXIO);
1977 } /* ng_ubt_connect */
1978 
1979 /*
1980  * Disconnect hook
1981  */
1982 
1983 Static int
1984 ng_ubt_disconnect(hook_p hook)
1985 {
1986 	ubt_softc_p	sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1987 
1988 	if (sc != NULL) {
1989 		if (hook != sc->sc_hook)
1990 			return (EINVAL);
1991 
1992 		ubt_reset(sc);
1993 		sc->sc_hook = NULL;
1994 	}
1995 
1996 	return (0);
1997 } /* ng_ubt_disconnect */
1998 
1999 /*
2000  * Process control message
2001  */
2002 
2003 Static int
2004 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
2005 {
2006 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
2007 	struct ng_mesg		*msg = NULL, *rsp = NULL;
2008 	struct ng_bt_mbufq	*q = NULL;
2009 	int			 error = 0, queue, qlen;
2010 
2011 	if (sc == NULL) {
2012 		NG_FREE_ITEM(item);
2013 		return (EHOSTDOWN);
2014 	}
2015 
2016 	NGI_GET_MSG(item, msg);
2017 
2018 	switch (msg->header.typecookie) {
2019 	case NGM_GENERIC_COOKIE:
2020 		switch (msg->header.cmd) {
2021 		case NGM_TEXT_STATUS:
2022 			NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
2023 			if (rsp == NULL)
2024 				error = ENOMEM;
2025 			else
2026 				snprintf(rsp->data, NG_TEXTRESPONSE,
2027 					"Hook: %s\n"   \
2028 					"Flags: %#x\n" \
2029 					"Debug: %d\n"  \
2030 					"CMD queue: [have:%d,max:%d]\n" \
2031 					"ACL queue: [have:%d,max:%d]\n" \
2032 					"SCO queue: [have:%d,max:%d]",
2033 					(sc->sc_hook != NULL)? NG_UBT_HOOK : "",
2034 					sc->sc_flags,
2035 					sc->sc_debug,
2036 					NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
2037 					sc->sc_cmdq.maxlen,
2038 					NG_BT_MBUFQ_LEN(&sc->sc_aclq),
2039 					sc->sc_aclq.maxlen,
2040 					NG_BT_MBUFQ_LEN(&sc->sc_scoq),
2041 					sc->sc_scoq.maxlen);
2042 			break;
2043 
2044 		default:
2045 			error = EINVAL;
2046 			break;
2047 		}
2048 		break;
2049 
2050 	case NGM_UBT_COOKIE:
2051 		switch (msg->header.cmd) {
2052 		case NGM_UBT_NODE_SET_DEBUG:
2053 			if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2054 				error = EMSGSIZE;
2055 			else
2056 				sc->sc_debug =
2057 					*((ng_ubt_node_debug_ep *)(msg->data));
2058 			break;
2059 
2060 		case NGM_UBT_NODE_GET_DEBUG:
2061 			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2062 				M_NOWAIT);
2063 			if (rsp == NULL)
2064 				error = ENOMEM;
2065 			else
2066 				*((ng_ubt_node_debug_ep *)(rsp->data)) =
2067 					sc->sc_debug;
2068                         break;
2069 
2070 		case NGM_UBT_NODE_SET_QLEN:
2071 			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2072 				error = EMSGSIZE;
2073 			else {
2074 				queue = ((ng_ubt_node_qlen_ep *)
2075 						(msg->data))->queue;
2076 				qlen = ((ng_ubt_node_qlen_ep *)
2077 						(msg->data))->qlen;
2078 
2079 				if (qlen <= 0) {
2080 					error = EINVAL;
2081 					break;
2082 				}
2083 
2084 				switch (queue) {
2085 				case NGM_UBT_NODE_QUEUE_CMD:
2086 					q = &sc->sc_cmdq;
2087 					break;
2088 
2089 				case NGM_UBT_NODE_QUEUE_ACL:
2090 					q = &sc->sc_aclq;
2091 					break;
2092 
2093 				case NGM_UBT_NODE_QUEUE_SCO:
2094 					q = &sc->sc_scoq;
2095 					break;
2096 
2097 				default:
2098 					q = NULL;
2099 					error = EINVAL;
2100 					break;
2101 				}
2102 
2103 				if (q != NULL)
2104 					q->maxlen = qlen;
2105 			}
2106 			break;
2107 
2108 		case NGM_UBT_NODE_GET_QLEN:
2109 			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2110 				error = EMSGSIZE;
2111 				break;
2112 			}
2113 
2114 			queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2115 			switch (queue) {
2116 			case NGM_UBT_NODE_QUEUE_CMD:
2117 				q = &sc->sc_cmdq;
2118 				break;
2119 
2120 			case NGM_UBT_NODE_QUEUE_ACL:
2121 				q = &sc->sc_aclq;
2122 				break;
2123 
2124 			case NGM_UBT_NODE_QUEUE_SCO:
2125 				q = &sc->sc_scoq;
2126 				break;
2127 
2128 			default:
2129 				q = NULL;
2130 				error = EINVAL;
2131 				break;
2132 			}
2133 
2134 			if (q != NULL) {
2135 				NG_MKRESPONSE(rsp, msg,
2136 					sizeof(ng_ubt_node_qlen_ep), M_NOWAIT);
2137 				if (rsp == NULL) {
2138 					error = ENOMEM;
2139 					break;
2140 				}
2141 
2142 				((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2143 					queue;
2144 				((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2145 					q->maxlen;
2146 			}
2147 			break;
2148 
2149 		case NGM_UBT_NODE_GET_STAT:
2150 			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2151 				M_NOWAIT);
2152 			if (rsp == NULL)
2153 				error = ENOMEM;
2154 			else
2155 				bcopy(&sc->sc_stat, rsp->data,
2156 					sizeof(ng_ubt_node_stat_ep));
2157 			break;
2158 
2159 		case NGM_UBT_NODE_RESET_STAT:
2160 			NG_UBT_STAT_RESET(sc->sc_stat);
2161 			break;
2162 
2163 		case NGM_UBT_NODE_DEV_NODES:
2164 			if (msg->header.arglen !=
2165 					sizeof(ng_ubt_node_dev_nodes_ep)) {
2166 				error = EMSGSIZE;
2167 				break;
2168 			}
2169 
2170 			if ((sc->sc_flags & UBT_ANY_DEV) ||
2171 			    sc->sc_hook != NULL) {
2172 				error = EBUSY;
2173 				break;
2174 			}
2175 
2176 			if (*((ng_ubt_node_dev_nodes_ep *)(msg->data)))
2177 				ubt_create_device_nodes(sc);
2178 			else
2179 				ubt_destroy_device_nodes(sc);
2180 			break;
2181 
2182 		default:
2183 			error = EINVAL;
2184 			break;
2185 		}
2186 		break;
2187 
2188 	default:
2189 		error = EINVAL;
2190 		break;
2191 	}
2192 
2193 	NG_RESPOND_MSG(error, node, item, rsp);
2194 	NG_FREE_MSG(msg);
2195 
2196 	return (error);
2197 } /* ng_ubt_rcvmsg */
2198 
2199 /*
2200  * Process data
2201  */
2202 
2203 Static int
2204 ng_ubt_rcvdata(hook_p hook, item_p item)
2205 {
2206 	ubt_softc_p		 sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2207 	struct mbuf		*m = NULL;
2208 	usbd_status		(*f)(ubt_softc_p) = NULL;
2209 	struct ng_bt_mbufq	*q = NULL;
2210 	int			 b, error = 0;
2211 
2212 	if (sc == NULL) {
2213 		error = EHOSTDOWN;
2214 		goto done;
2215 	}
2216 
2217 	if (hook != sc->sc_hook) {
2218 		error = EINVAL;
2219 		goto done;
2220 	}
2221 
2222 	/* Deatch mbuf and get HCI frame type */
2223 	NGI_GET_M(item, m);
2224 
2225 	/* Process HCI frame */
2226 	switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
2227 	case NG_HCI_CMD_PKT:
2228 		f = ubt_request_start;
2229 		q = &sc->sc_cmdq;
2230 		b = UBT_CMD_XMIT;
2231 		break;
2232 
2233 	case NG_HCI_ACL_DATA_PKT:
2234 		f = ubt_bulk_out_start;
2235 		q = &sc->sc_aclq;
2236 		b = UBT_ACL_XMIT;
2237 		break;
2238 
2239 #if __broken__ /* XXX FIXME */
2240 	case NG_HCI_SCO_DATA_PKT:
2241 		f = ubt_isoc_out_start;
2242 		q = &sc->sc_scoq;
2243 		b = UBT_SCO_XMIT;
2244 		break;
2245 #endif /* __broken__ */
2246 
2247 	default:
2248 		NG_UBT_ERR(
2249 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2250 			__func__, USBDEVNAME(sc->sc_dev), *mtod(m, u_int8_t *),
2251 			m->m_pkthdr.len);
2252 
2253 		NG_FREE_M(m);
2254 		error = EINVAL;
2255 
2256 		goto done;
2257 		/* NOT REACHED */
2258 	}
2259 
2260 	/* Loose frame type, if required */
2261 	if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2262 		m_adj(m, sizeof(u_int8_t));
2263 
2264 	if (NG_BT_MBUFQ_FULL(q)) {
2265 		NG_UBT_ERR(
2266 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2267 			__func__, USBDEVNAME(sc->sc_dev),
2268 			*mtod(m, u_int8_t *), m->m_pkthdr.len);
2269 
2270 		NG_FREE_M(m);
2271 	} else
2272 		NG_BT_MBUFQ_ENQUEUE(q, m);
2273 
2274 	if (!(sc->sc_flags & b))
2275 		if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2276 			error = EIO;
2277 done:
2278 	NG_FREE_ITEM(item);
2279 
2280 	return (error);
2281 } /* ng_ubt_rcvdata */
2282 
2283 /****************************************************************************
2284  ****************************************************************************
2285  **                              Device specific
2286  ****************************************************************************
2287  ****************************************************************************/
2288 
2289 /*
2290  * Open endpoint device
2291  * XXX FIXME softc locking
2292  */
2293 
2294 Static int
2295 ubt_open(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
2296 {
2297 	ubt_softc_p	sc = NULL;
2298 	int		ep = UBT_ENDPOINT(dev);
2299 
2300 	USB_GET_SC_OPEN(ubt, UBT_UNIT(dev), sc); /* check for sc != NULL */
2301 	if (sc->sc_dying)
2302 		return (ENXIO);
2303 
2304 	if (ep == USB_CONTROL_ENDPOINT) {
2305 		if (sc->sc_flags & UBT_CTRL_DEV)
2306 			return (EBUSY);
2307 
2308 		sc->sc_flags |= UBT_CTRL_DEV;
2309 	} else if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2310 		if (sc->sc_flags & UBT_INTR_DEV)
2311 			return (EBUSY);
2312 		if (sc->sc_intr_pipe == NULL)
2313 			return (ENXIO);
2314 
2315 		sc->sc_flags |= UBT_INTR_DEV;
2316 	} else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2317 		if (sc->sc_flags & UBT_BULK_DEV)
2318 			return (EBUSY);
2319 		if (sc->sc_bulk_in_pipe == NULL || sc->sc_bulk_out_pipe == NULL)
2320 			return (ENXIO);
2321 
2322 		sc->sc_flags |= UBT_BULK_DEV;
2323 	} else
2324 		return (EINVAL);
2325 
2326 	return (0);
2327 } /* ubt_open */
2328 
2329 /*
2330  * Close endpoint device
2331  * XXX FIXME softc locking
2332  */
2333 
2334 Static int
2335 ubt_close(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
2336 {
2337 	ubt_softc_p	sc = NULL;
2338 	int		ep = UBT_ENDPOINT(dev);
2339 
2340 	USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2341 	if (sc == NULL)
2342 		return (ENXIO);
2343 
2344 	if (ep == USB_CONTROL_ENDPOINT)
2345 		sc->sc_flags &= ~UBT_CTRL_DEV;
2346 	else if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2347 		if (sc->sc_intr_pipe != NULL)
2348 			usbd_abort_pipe(sc->sc_intr_pipe);
2349 
2350 		sc->sc_flags &= ~UBT_INTR_DEV;
2351 	} else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2352 		/* Close both in and out bulk pipes */
2353 		if (sc->sc_bulk_in_pipe != NULL)
2354 			usbd_abort_pipe(sc->sc_bulk_in_pipe);
2355 
2356 		if (sc->sc_bulk_out_pipe != NULL)
2357 			usbd_abort_pipe(sc->sc_bulk_out_pipe);
2358 
2359 		sc->sc_flags &= ~UBT_BULK_DEV;
2360 	} else
2361 		return (EINVAL);
2362 
2363 	return (0);
2364 } /* ubt_close */
2365 
2366 /*
2367  * Read from the endpoint device
2368  * XXX FIXME softc locking
2369  */
2370 
2371 Static int
2372 ubt_read(struct cdev *dev, struct uio *uio, int flag)
2373 {
2374 	ubt_softc_p		sc = NULL;
2375 	int			error = 0, n, tn, ep = UBT_ENDPOINT(dev);
2376 	usbd_status		status;
2377 	usbd_pipe_handle	pipe = NULL;
2378 	usbd_xfer_handle	xfer = NULL;
2379 	u_int8_t		buf[UBT_BSIZE];
2380 
2381 	USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2382 	if (sc == NULL || sc->sc_dying)
2383 		return (ENXIO);
2384 
2385 	if (ep == USB_CONTROL_ENDPOINT)
2386 		return (EOPNOTSUPP);
2387 
2388 	if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2389 		pipe = sc->sc_intr_pipe;
2390 		xfer = sc->sc_intr_xfer;
2391 	} else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2392 		pipe = sc->sc_bulk_in_pipe;
2393 		xfer = sc->sc_bulk_in_xfer;
2394 	} else
2395 		return (EINVAL);
2396 
2397 	if (pipe == NULL || xfer == NULL)
2398 		return (ENXIO);
2399 
2400 	sc->sc_refcnt ++;
2401 
2402 	while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
2403 		tn = n;
2404 		status = usbd_bulk_transfer(xfer, pipe, USBD_SHORT_XFER_OK,
2405 				USBD_DEFAULT_TIMEOUT, buf, &tn, "ubtrd");
2406 		switch (status) {
2407 		case USBD_NORMAL_COMPLETION:
2408 			error = uiomove(buf, tn, uio);
2409 			break;
2410 
2411 		case USBD_INTERRUPTED:
2412 			error = EINTR;
2413 			break;
2414 
2415 		case USBD_TIMEOUT:
2416 			error = ETIMEDOUT;
2417 			break;
2418 
2419 		default:
2420 			error = EIO;
2421 			break;
2422 		}
2423 
2424 		if (error != 0 || tn < n)
2425 			break;
2426 	}
2427 
2428 	if (-- sc->sc_refcnt < 0)
2429 		usb_detach_wakeup(USBDEV(sc->sc_dev));
2430 
2431 	return (error);
2432 } /* ubt_read */
2433 
2434 /*
2435  * Write into the endpoint device
2436  * XXX FIXME softc locking
2437  */
2438 
2439 Static int
2440 ubt_write(struct cdev *dev, struct uio *uio, int flag)
2441 {
2442 	ubt_softc_p	sc = NULL;
2443 	int		error = 0, n, ep = UBT_ENDPOINT(dev);
2444 	usbd_status	status;
2445 	u_int8_t	buf[UBT_BSIZE];
2446 
2447 	USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2448 	if (sc == NULL || sc->sc_dying)
2449 		return (ENXIO);
2450 
2451 	if (ep == USB_CONTROL_ENDPOINT || ep == UE_GET_ADDR(sc->sc_intr_ep))
2452 		return (EOPNOTSUPP);
2453 	if (ep != UE_GET_ADDR(sc->sc_bulk_in_ep))
2454 		return (EINVAL);
2455 
2456 	sc->sc_refcnt ++;
2457 
2458 	while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
2459 		error = uiomove(buf, n, uio);
2460 		if (error != 0)
2461 			break;
2462 
2463 		status = usbd_bulk_transfer(sc->sc_bulk_out_xfer,
2464 				sc->sc_bulk_out_pipe, 0, USBD_DEFAULT_TIMEOUT,
2465 				buf, &n,"ubtwr");
2466 		switch (status) {
2467 		case USBD_NORMAL_COMPLETION:
2468 			break;
2469 
2470 		case USBD_INTERRUPTED:
2471 			error = EINTR;
2472 			break;
2473 
2474 		case USBD_TIMEOUT:
2475 			error = ETIMEDOUT;
2476 			break;
2477 
2478 		default:
2479 			error = EIO;
2480 			break;
2481 		}
2482 
2483 		if (error != 0)
2484 			break;
2485 	}
2486 
2487 	if (-- sc->sc_refcnt < 0)
2488 		usb_detach_wakeup(USBDEV(sc->sc_dev));
2489 
2490 	return (error);
2491 } /* ubt_write */
2492 
2493 /*
2494  * Process ioctl on the endpoint device. Mostly stolen from ugen(4)
2495  * XXX FIXME softc locking
2496  */
2497 
2498 Static int
2499 ubt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
2500 {
2501 	ubt_softc_p		 sc = NULL;
2502 	int			 len, error = 0, ep = UBT_ENDPOINT(dev);
2503 	usbd_status		 status;
2504 	struct usb_string_desc	*si = NULL;
2505 	struct usb_ctl_request	*ur = NULL;
2506 	void			*ptr = NULL;
2507 	struct iovec		 iov;
2508 	struct uio		 uio;
2509 
2510 	USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2511 	if (sc == NULL || sc->sc_dying)
2512 		return (ENXIO);
2513 
2514 	if (ep != USB_CONTROL_ENDPOINT)
2515 		return (EOPNOTSUPP);
2516 
2517 	sc->sc_refcnt ++;
2518 
2519 	switch (cmd) {
2520 	case USB_GET_DEVICE_DESC:
2521 		*(usb_device_descriptor_t *) data =
2522 				*usbd_get_device_descriptor(sc->sc_udev);
2523 		break;
2524 
2525 	case USB_GET_STRING_DESC:
2526 		si = (struct usb_string_desc *) data;
2527 		status = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
2528 				si->usd_language_id, &si->usd_desc, &len);
2529 		if (status != USBD_NORMAL_COMPLETION)
2530 			error = EINVAL;
2531 		break;
2532 
2533 	case USB_DO_REQUEST:
2534 		ur = (void *) data;
2535 		len = UGETW(ur->ucr_request.wLength);
2536 
2537 		if (!(flag & FWRITE)) {
2538 			error = EPERM;
2539 			break;
2540 		}
2541 
2542 		/* Avoid requests that would damage the bus integrity. */
2543 		if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
2544 		     ur->ucr_request.bRequest == UR_SET_ADDRESS) ||
2545 		    (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
2546 		     ur->ucr_request.bRequest == UR_SET_CONFIG) ||
2547 		    (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE &&
2548 		     ur->ucr_request.bRequest == UR_SET_INTERFACE) ||
2549 		    len < 0 || len > 32767) {
2550 			error = EINVAL;
2551 			break;
2552 		}
2553 
2554 		if (len != 0) {
2555 			iov.iov_base = (caddr_t) ur->ucr_data;
2556 			iov.iov_len = len;
2557 
2558 			uio.uio_iov = &iov;
2559 			uio.uio_iovcnt = 1;
2560 			uio.uio_resid = len;
2561 			uio.uio_offset = 0;
2562 			uio.uio_segflg = UIO_USERSPACE;
2563 			uio.uio_rw = ur->ucr_request.bmRequestType & UT_READ ?
2564 						UIO_READ : UIO_WRITE;
2565 			uio.uio_procp = p;
2566 
2567 			ptr = malloc(len, M_TEMP, M_WAITOK);
2568 			if (uio.uio_rw == UIO_WRITE) {
2569 				error = uiomove(ptr, len, &uio);
2570 				if (error != 0)
2571 					goto ret;
2572 			}
2573 		}
2574 
2575 		status = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
2576 				ptr, ur->ucr_flags, &ur->ucr_actlen,
2577 				USBD_DEFAULT_TIMEOUT);
2578 		if (status != USBD_NORMAL_COMPLETION) {
2579 			error = EIO;
2580 			goto ret;
2581 		}
2582 
2583 		if (len != 0) {
2584 			if (uio.uio_rw == UIO_READ) {
2585 				error = uiomove(ptr, len, &uio);
2586 				if (error != 0)
2587 					goto ret;
2588 			}
2589 		}
2590 ret:
2591 		if (ptr != NULL)
2592 			free(ptr, M_TEMP);
2593 		break;
2594 
2595 	case USB_GET_DEVICEINFO:
2596 		usbd_fill_deviceinfo(sc->sc_udev,
2597 			(struct usb_device_info *) data, 1);
2598 		break;
2599 
2600 	default:
2601 		error = EINVAL;
2602 		break;
2603 	}
2604 
2605 	if (-- sc->sc_refcnt < 0)
2606 		usb_detach_wakeup(USBDEV(sc->sc_dev));
2607 
2608 	return (error);
2609 } /* ubt_ioctl */
2610 
2611 /*
2612  * Poll the endpoint device
2613  * XXX FIXME softc locking
2614  */
2615 
2616 Static int
2617 ubt_poll(struct cdev *dev, int events, usb_proc_ptr p)
2618 {
2619 	ubt_softc_p	sc = NULL;
2620 	int		revents = 0, ep = UBT_ENDPOINT(dev);
2621 
2622 	USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2623 	if (sc == NULL || sc->sc_dying)
2624 		return (ENXIO);
2625 
2626 	if (ep == USB_CONTROL_ENDPOINT)
2627 		return (EOPNOTSUPP);
2628 
2629 	if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2630 		if (sc->sc_intr_pipe != NULL)
2631 			revents |= events & (POLLIN | POLLRDNORM);
2632 		else
2633 			revents = EIO;
2634 	} else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2635 		if (sc->sc_bulk_in_pipe != NULL)
2636 			revents |= events & (POLLIN | POLLRDNORM);
2637 
2638 		if (sc->sc_bulk_out_pipe != NULL)
2639 			revents |= events & (POLLOUT | POLLWRNORM);
2640 
2641 		if (revents == 0)
2642 			revents = EIO; /* both pipes closed */
2643 	} else
2644 		revents = EINVAL;
2645 
2646 	return (revents);
2647 } /* ubt_poll */
2648 
2649 /*
2650  * Create device nodes for all endpoints. Must be called with node locked.
2651  */
2652 
2653 Static void
2654 ubt_create_device_nodes(ubt_softc_p sc)
2655 {
2656 	int	ep;
2657 
2658 	KASSERT((sc->sc_hook == NULL), (
2659 "%s: %s - hook != NULL!\n", __func__, USBDEVNAME(sc->sc_dev)));
2660 
2661 	/* Control device */
2662 	if (sc->sc_ctrl_dev == NULL)
2663 		sc->sc_ctrl_dev = make_dev(&ubt_cdevsw,
2664 					UBT_MINOR(USBDEVUNIT(sc->sc_dev), 0),
2665 					UID_ROOT, GID_OPERATOR, 0644,
2666 					"%s", USBDEVNAME(sc->sc_dev));
2667 
2668 	/* Interrupt device */
2669 	if (sc->sc_intr_dev == NULL && sc->sc_intr_ep != -1) {
2670 		ep = UE_GET_ADDR(sc->sc_intr_ep);
2671 		sc->sc_intr_dev = make_dev(&ubt_cdevsw,
2672 					UBT_MINOR(USBDEVUNIT(sc->sc_dev), ep),
2673 					UID_ROOT, GID_OPERATOR, 0644,
2674 					"%s.%d", USBDEVNAME(sc->sc_dev), ep);
2675 	}
2676 
2677 	/*
2678 	 * Bulk-in and bulk-out device
2679 	 * XXX will create one device for both in and out endpoints.
2680 	 * XXX note that address of the in and out endpoint should be the same
2681 	 */
2682 
2683 	if (sc->sc_bulk_dev == NULL &&
2684 	    sc->sc_bulk_in_ep != -1 && sc->sc_bulk_out_ep != -1 &&
2685 	    UE_GET_ADDR(sc->sc_bulk_in_ep) == UE_GET_ADDR(sc->sc_bulk_out_ep)) {
2686 		ep = UE_GET_ADDR(sc->sc_bulk_in_ep);
2687 		sc->sc_bulk_dev = make_dev(&ubt_cdevsw,
2688 					UBT_MINOR(USBDEVUNIT(sc->sc_dev), ep),
2689 					UID_ROOT, GID_OPERATOR, 0644,
2690 					"%s.%d", USBDEVNAME(sc->sc_dev), ep);
2691 	}
2692 } /* ubt_create_device_nodes */
2693 
2694 /*
2695  * Destroy device nodes for all endpoints
2696  * XXX FIXME locking
2697  */
2698 
2699 Static void
2700 ubt_destroy_device_nodes(ubt_softc_p sc)
2701 {
2702 	/*
2703 	 * Wait for processes to go away. This should be safe as we will not
2704 	 * call ubt_destroy_device_nodes() from Netgraph unless all devices
2705 	 * were closed (and thus no active processes).
2706 	 */
2707 
2708 	if (-- sc->sc_refcnt >= 0) {
2709 		ubt_reset(sc);
2710 		usb_detach_wait(USBDEV(sc->sc_dev));
2711 	}
2712 
2713 	sc->sc_refcnt = 0;
2714 
2715 	/* Destroy device nodes */
2716 	if (sc->sc_bulk_dev != NULL) {
2717 		destroy_dev(sc->sc_bulk_dev);
2718 		sc->sc_bulk_dev = NULL;
2719 	}
2720 
2721 	if (sc->sc_intr_dev != NULL) {
2722 		destroy_dev(sc->sc_intr_dev);
2723 		sc->sc_intr_dev = NULL;
2724 	}
2725 
2726 	if (sc->sc_ctrl_dev != NULL) {
2727 		destroy_dev(sc->sc_ctrl_dev);
2728 		sc->sc_ctrl_dev = NULL;
2729 	}
2730 } /* ubt_destroy_device_nodes */
2731 
2732