1/*
2 * ng_ubt.c
3 */
4
5/*-
6 * Copyright (c) 2001-2009 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/*
35 * NOTE: ng_ubt2 driver has a split personality. On one side it is
36 * a USB device driver and on the other it is a Netgraph node. This
37 * driver will *NOT* create traditional /dev/ enties, only Netgraph
38 * node.
39 *
40 * NOTE ON LOCKS USED: ng_ubt2 drives uses 2 locks (mutexes)
41 *
42 * 1) sc_if_mtx - lock for device's interface #0 and #1. This lock is used
43 *    by USB for any USB request going over device's interface #0 and #1,
44 *    i.e. interrupt, control, bulk and isoc. transfers.
45 *
46 * 2) sc_ng_mtx - this lock is used to protect shared (between USB, Netgraph
47 *    and Taskqueue) data, such as outgoing mbuf queues, task flags and hook
48 *    pointer. This lock *SHOULD NOT* be grabbed for a long time. In fact,
49 *    think of it as a spin lock.
50 *
51 * NOTE ON LOCKING STRATEGY: ng_ubt2 driver operates in 3 different contexts.
52 *
53 * 1) USB context. This is where all the USB related stuff happens. All
54 *    callbacks run in this context. All callbacks are called (by USB) with
55 *    appropriate interface lock held. It is (generally) allowed to grab
56 *    any additional locks.
57 *
58 * 2) Netgraph context. This is where all the Netgraph related stuff happens.
59 *    Since we mark node as WRITER, the Netgraph node will be "locked" (from
60 *    Netgraph point of view). Any variable that is only modified from the
61 *    Netgraph context does not require any additonal locking. It is generally
62 *    *NOT* allowed to grab *ANY* additional locks. Whatever you do, *DO NOT*
63 *    grab any lock in the Netgraph context that could cause de-scheduling of
64 *    the Netgraph thread for significant amount of time. In fact, the only
65 *    lock that is allowed in the Netgraph context is the sc_ng_mtx lock.
66 *    Also make sure that any code that is called from the Netgraph context
67 *    follows the rule above.
68 *
69 * 3) Taskqueue context. This is where ubt_task runs. Since we are generally
70 *    NOT allowed to grab any lock that could cause de-scheduling in the
71 *    Netgraph context, and, USB requires us to grab interface lock before
72 *    doing things with transfers, it is safer to transition from the Netgraph
73 *    context to the Taskqueue context before we can call into USB subsystem.
74 *
75 * So, to put everything together, the rules are as follows.
76 *	It is OK to call from the USB context or the Taskqueue context into
77 * the Netgraph context (i.e. call NG_SEND_xxx functions). In other words
78 * it is allowed to call into the Netgraph context with locks held.
79 *	Is it *NOT* OK to call from the Netgraph context into the USB context,
80 * because USB requires us to grab interface locks, and, it is safer to
81 * avoid it. So, to make things safer we set task flags to indicate which
82 * actions we want to perform and schedule ubt_task which would run in the
83 * Taskqueue context.
84 *	Is is OK to call from the Taskqueue context into the USB context,
85 * and, ubt_task does just that (i.e. grabs appropriate interface locks
86 * before calling into USB).
87 *	Access to the outgoing queues, task flags and hook pointer is
88 * controlled by the sc_ng_mtx lock. It is an unavoidable evil. Again,
89 * sc_ng_mtx should really be a spin lock (and it is very likely to an
90 * equivalent of spin lock due to adaptive nature of FreeBSD mutexes).
91 *	All USB callbacks accept softc pointer as a private data. USB ensures
92 * that this pointer is valid.
93 */
94
95#include <sys/stdint.h>
96#include <sys/stddef.h>
97#include <sys/param.h>
98#include <sys/queue.h>
99#include <sys/types.h>
100#include <sys/systm.h>
101#include <sys/kernel.h>
102#include <sys/bus.h>
103#include <sys/module.h>
104#include <sys/lock.h>
105#include <sys/mutex.h>
106#include <sys/condvar.h>
107#include <sys/sysctl.h>
108#include <sys/sx.h>
109#include <sys/unistd.h>
110#include <sys/callout.h>
111#include <sys/malloc.h>
112#include <sys/priv.h>
113
114#include "usbdevs.h"
115#include <dev/usb/usb.h>
116#include <dev/usb/usbdi.h>
117#include <dev/usb/usbdi_util.h>
118
119#define	USB_DEBUG_VAR usb_debug
120#include <dev/usb/usb_debug.h>
121#include <dev/usb/usb_busdma.h>
122
123#include <sys/mbuf.h>
124#include <sys/taskqueue.h>
125
126#include <netgraph/ng_message.h>
127#include <netgraph/netgraph.h>
128#include <netgraph/ng_parse.h>
129#include <netgraph/bluetooth/include/ng_bluetooth.h>
130#include <netgraph/bluetooth/include/ng_hci.h>
131#include <netgraph/bluetooth/include/ng_ubt.h>
132#include <netgraph/bluetooth/drivers/ubt/ng_ubt_var.h>
133
134static int		ubt_modevent(module_t, int, void *);
135static device_probe_t	ubt_probe;
136static device_attach_t	ubt_attach;
137static device_detach_t	ubt_detach;
138
139static void		ubt_task_schedule(ubt_softc_p, int);
140static task_fn_t	ubt_task;
141
142#define	ubt_xfer_start(sc, i)	usbd_transfer_start((sc)->sc_xfer[(i)])
143
144/* Netgraph methods */
145static ng_constructor_t	ng_ubt_constructor;
146static ng_shutdown_t	ng_ubt_shutdown;
147static ng_newhook_t	ng_ubt_newhook;
148static ng_connect_t	ng_ubt_connect;
149static ng_disconnect_t	ng_ubt_disconnect;
150static ng_rcvmsg_t	ng_ubt_rcvmsg;
151static ng_rcvdata_t	ng_ubt_rcvdata;
152
153/* Queue length */
154static const struct ng_parse_struct_field	ng_ubt_node_qlen_type_fields[] =
155{
156	{ "queue", &ng_parse_int32_type, },
157	{ "qlen",  &ng_parse_int32_type, },
158	{ NULL, }
159};
160static const struct ng_parse_type		ng_ubt_node_qlen_type =
161{
162	&ng_parse_struct_type,
163	&ng_ubt_node_qlen_type_fields
164};
165
166/* Stat info */
167static const struct ng_parse_struct_field	ng_ubt_node_stat_type_fields[] =
168{
169	{ "pckts_recv", &ng_parse_uint32_type, },
170	{ "bytes_recv", &ng_parse_uint32_type, },
171	{ "pckts_sent", &ng_parse_uint32_type, },
172	{ "bytes_sent", &ng_parse_uint32_type, },
173	{ "oerrors",    &ng_parse_uint32_type, },
174	{ "ierrors",    &ng_parse_uint32_type, },
175	{ NULL, }
176};
177static const struct ng_parse_type		ng_ubt_node_stat_type =
178{
179	&ng_parse_struct_type,
180	&ng_ubt_node_stat_type_fields
181};
182
183/* Netgraph node command list */
184static const struct ng_cmdlist			ng_ubt_cmdlist[] =
185{
186	{
187		NGM_UBT_COOKIE,
188		NGM_UBT_NODE_SET_DEBUG,
189		"set_debug",
190		&ng_parse_uint16_type,
191		NULL
192	},
193	{
194		NGM_UBT_COOKIE,
195		NGM_UBT_NODE_GET_DEBUG,
196		"get_debug",
197		NULL,
198		&ng_parse_uint16_type
199	},
200	{
201		NGM_UBT_COOKIE,
202		NGM_UBT_NODE_SET_QLEN,
203		"set_qlen",
204		&ng_ubt_node_qlen_type,
205		NULL
206	},
207	{
208		NGM_UBT_COOKIE,
209		NGM_UBT_NODE_GET_QLEN,
210		"get_qlen",
211		&ng_ubt_node_qlen_type,
212		&ng_ubt_node_qlen_type
213	},
214	{
215		NGM_UBT_COOKIE,
216		NGM_UBT_NODE_GET_STAT,
217		"get_stat",
218		NULL,
219		&ng_ubt_node_stat_type
220	},
221	{
222		NGM_UBT_COOKIE,
223		NGM_UBT_NODE_RESET_STAT,
224		"reset_stat",
225		NULL,
226		NULL
227	},
228	{ 0, }
229};
230
231/* Netgraph node type */
232static struct ng_type	typestruct =
233{
234	.version = 	NG_ABI_VERSION,
235	.name =		NG_UBT_NODE_TYPE,
236	.constructor =	ng_ubt_constructor,
237	.rcvmsg =	ng_ubt_rcvmsg,
238	.shutdown =	ng_ubt_shutdown,
239	.newhook =	ng_ubt_newhook,
240	.connect =	ng_ubt_connect,
241	.rcvdata =	ng_ubt_rcvdata,
242	.disconnect =	ng_ubt_disconnect,
243	.cmdlist =	ng_ubt_cmdlist
244};
245
246/****************************************************************************
247 ****************************************************************************
248 **                              USB specific
249 ****************************************************************************
250 ****************************************************************************/
251
252/* USB methods */
253static usb_callback_t	ubt_ctrl_write_callback;
254static usb_callback_t	ubt_intr_read_callback;
255static usb_callback_t	ubt_bulk_read_callback;
256static usb_callback_t	ubt_bulk_write_callback;
257static usb_callback_t	ubt_isoc_read_callback;
258static usb_callback_t	ubt_isoc_write_callback;
259
260static int		ubt_fwd_mbuf_up(ubt_softc_p, struct mbuf **);
261static int		ubt_isoc_read_one_frame(struct usb_xfer *, int);
262
263/*
264 * USB config
265 *
266 * The following desribes usb transfers that could be submitted on USB device.
267 *
268 * Interface 0 on the USB device must present the following endpoints
269 *	1) Interrupt endpoint to receive HCI events
270 *	2) Bulk IN endpoint to receive ACL data
271 *	3) Bulk OUT endpoint to send ACL data
272 *
273 * Interface 1 on the USB device must present the following endpoints
274 *	1) Isochronous IN endpoint to receive SCO data
275 *	2) Isochronous OUT endpoint to send SCO data
276 */
277
278static const struct usb_config		ubt_config[UBT_N_TRANSFER] =
279{
280	/*
281	 * Interface #0
282 	 */
283
284	/* Outgoing bulk transfer - ACL packets */
285	[UBT_IF_0_BULK_DT_WR] = {
286		.type =		UE_BULK,
287		.endpoint =	UE_ADDR_ANY,
288		.direction =	UE_DIR_OUT,
289		.if_index = 	0,
290		.bufsize =	UBT_BULK_WRITE_BUFFER_SIZE,
291		.flags =	{ .pipe_bof = 1, .force_short_xfer = 1, },
292		.callback =	&ubt_bulk_write_callback,
293	},
294	/* Incoming bulk transfer - ACL packets */
295	[UBT_IF_0_BULK_DT_RD] = {
296		.type =		UE_BULK,
297		.endpoint =	UE_ADDR_ANY,
298		.direction =	UE_DIR_IN,
299		.if_index = 	0,
300		.bufsize =	UBT_BULK_READ_BUFFER_SIZE,
301		.flags =	{ .pipe_bof = 1, .short_xfer_ok = 1, },
302		.callback =	&ubt_bulk_read_callback,
303	},
304	/* Incoming interrupt transfer - HCI events */
305	[UBT_IF_0_INTR_DT_RD] = {
306		.type =		UE_INTERRUPT,
307		.endpoint =	UE_ADDR_ANY,
308		.direction =	UE_DIR_IN,
309		.if_index = 	0,
310		.flags =	{ .pipe_bof = 1, .short_xfer_ok = 1, },
311		.bufsize =	UBT_INTR_BUFFER_SIZE,
312		.callback =	&ubt_intr_read_callback,
313	},
314	/* Outgoing control transfer - HCI commands */
315	[UBT_IF_0_CTRL_DT_WR] = {
316		.type =		UE_CONTROL,
317		.endpoint =	0x00,	/* control pipe */
318		.direction =	UE_DIR_ANY,
319		.if_index = 	0,
320		.bufsize =	UBT_CTRL_BUFFER_SIZE,
321		.callback =	&ubt_ctrl_write_callback,
322		.timeout =	5000,	/* 5 seconds */
323	},
324
325	/*
326	 * Interface #1
327 	 */
328
329	/* Incoming isochronous transfer #1 - SCO packets */
330	[UBT_IF_1_ISOC_DT_RD1] = {
331		.type =		UE_ISOCHRONOUS,
332		.endpoint =	UE_ADDR_ANY,
333		.direction =	UE_DIR_IN,
334		.if_index = 	1,
335		.bufsize =	0,	/* use "wMaxPacketSize * frames" */
336		.frames =	UBT_ISOC_NFRAMES,
337		.flags =	{ .short_xfer_ok = 1, },
338		.callback =	&ubt_isoc_read_callback,
339	},
340	/* Incoming isochronous transfer #2 - SCO packets */
341	[UBT_IF_1_ISOC_DT_RD2] = {
342		.type =		UE_ISOCHRONOUS,
343		.endpoint =	UE_ADDR_ANY,
344		.direction =	UE_DIR_IN,
345		.if_index = 	1,
346		.bufsize =	0,	/* use "wMaxPacketSize * frames" */
347		.frames =	UBT_ISOC_NFRAMES,
348		.flags =	{ .short_xfer_ok = 1, },
349		.callback =	&ubt_isoc_read_callback,
350	},
351	/* Outgoing isochronous transfer #1 - SCO packets */
352	[UBT_IF_1_ISOC_DT_WR1] = {
353		.type =		UE_ISOCHRONOUS,
354		.endpoint =	UE_ADDR_ANY,
355		.direction =	UE_DIR_OUT,
356		.if_index = 	1,
357		.bufsize =	0,	/* use "wMaxPacketSize * frames" */
358		.frames =	UBT_ISOC_NFRAMES,
359		.flags =	{ .short_xfer_ok = 1, },
360		.callback =	&ubt_isoc_write_callback,
361	},
362	/* Outgoing isochronous transfer #2 - SCO packets */
363	[UBT_IF_1_ISOC_DT_WR2] = {
364		.type =		UE_ISOCHRONOUS,
365		.endpoint =	UE_ADDR_ANY,
366		.direction =	UE_DIR_OUT,
367		.if_index = 	1,
368		.bufsize =	0,	/* use "wMaxPacketSize * frames" */
369		.frames =	UBT_ISOC_NFRAMES,
370		.flags =	{ .short_xfer_ok = 1, },
371		.callback =	&ubt_isoc_write_callback,
372	},
373};
374
375/*
376 * If for some reason device should not be attached then put
377 * VendorID/ProductID pair into the list below. The format is
378 * as follows:
379 *
380 *	{ USB_VPI(VENDOR_ID, PRODUCT_ID, 0) },
381 *
382 * where VENDOR_ID and PRODUCT_ID are hex numbers.
383 */
384
385static const STRUCT_USB_HOST_ID ubt_ignore_devs[] =
386{
387	/* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */
388	{ USB_VPI(USB_VENDOR_AVM, 0x2200, 0) },
389};
390
391/* List of supported bluetooth devices */
392static const STRUCT_USB_HOST_ID ubt_devs[] =
393{
394	/* Generic Bluetooth class devices */
395	{ USB_IFACE_CLASS(UDCLASS_WIRELESS),
396	  USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
397	  USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
398
399	/* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
400	{ USB_VPI(USB_VENDOR_AVM, 0x3800, 0) },
401
402	/* Broadcom USB dongles, mostly BCM20702 and BCM20702A0 */
403	{ USB_VENDOR(USB_VENDOR_BROADCOM),
404	  USB_IFACE_CLASS(UICLASS_VENDOR),
405	  USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
406	  USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
407
408	/* Apple-specific (Broadcom) devices */
409	{ USB_VENDOR(USB_VENDOR_APPLE),
410	  USB_IFACE_CLASS(UICLASS_VENDOR),
411	  USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
412	  USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
413
414	/* Foxconn - Hon Hai */
415	{ USB_VENDOR(USB_VENDOR_FOXCONN),
416	  USB_IFACE_CLASS(UICLASS_VENDOR),
417	  USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
418	  USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
419
420	/* MediaTek MT76x0E */
421	{ USB_VPI(USB_VENDOR_MEDIATEK, 0x763f, 0) },
422
423	/* Broadcom SoftSailing reporting vendor specific */
424	{ USB_VPI(USB_VENDOR_BROADCOM, 0x21e1, 0) },
425
426	/* Apple MacBookPro 7,1 */
427	{ USB_VPI(USB_VENDOR_APPLE, 0x8213, 0) },
428
429	/* Apple iMac11,1 */
430	{ USB_VPI(USB_VENDOR_APPLE, 0x8215, 0) },
431
432	/* Apple MacBookPro6,2 */
433	{ USB_VPI(USB_VENDOR_APPLE, 0x8218, 0) },
434
435	/* Apple MacBookAir3,1, MacBookAir3,2 */
436	{ USB_VPI(USB_VENDOR_APPLE, 0x821b, 0) },
437
438	/* Apple MacBookAir4,1 */
439	{ USB_VPI(USB_VENDOR_APPLE, 0x821f, 0) },
440
441	/* MacBookAir6,1 */
442	{ USB_VPI(USB_VENDOR_APPLE, 0x828f, 0) },
443
444	/* Apple MacBookPro8,2 */
445	{ USB_VPI(USB_VENDOR_APPLE, 0x821a, 0) },
446
447	/* Apple MacMini5,1 */
448	{ USB_VPI(USB_VENDOR_APPLE, 0x8281, 0) },
449
450	/* Bluetooth Ultraport Module from IBM */
451	{ USB_VPI(USB_VENDOR_TDK, 0x030a, 0) },
452
453	/* ALPS Modules with non-standard ID */
454	{ USB_VPI(USB_VENDOR_ALPS, 0x3001, 0) },
455	{ USB_VPI(USB_VENDOR_ALPS, 0x3002, 0) },
456
457	{ USB_VPI(USB_VENDOR_ERICSSON2, 0x1002, 0) },
458
459	/* Canyon CN-BTU1 with HID interfaces */
460	{ USB_VPI(USB_VENDOR_CANYON, 0x0000, 0) },
461
462	/* Broadcom BCM20702A0 */
463	{ USB_VPI(USB_VENDOR_ASUS, 0x17b5, 0) },
464	{ USB_VPI(USB_VENDOR_ASUS, 0x17cb, 0) },
465	{ USB_VPI(USB_VENDOR_LITEON, 0x2003, 0) },
466	{ USB_VPI(USB_VENDOR_FOXCONN, 0xe042, 0) },
467	{ USB_VPI(USB_VENDOR_DELL, 0x8197, 0) },
468};
469
470/*
471 * Probe for a USB Bluetooth device.
472 * USB context.
473 */
474
475static int
476ubt_probe(device_t dev)
477{
478	struct usb_attach_arg	*uaa = device_get_ivars(dev);
479	int error;
480
481	if (uaa->usb_mode != USB_MODE_HOST)
482		return (ENXIO);
483
484	if (uaa->info.bIfaceIndex != 0)
485		return (ENXIO);
486
487	if (usbd_lookup_id_by_uaa(ubt_ignore_devs,
488			sizeof(ubt_ignore_devs), uaa) == 0)
489		return (ENXIO);
490
491	error = usbd_lookup_id_by_uaa(ubt_devs, sizeof(ubt_devs), uaa);
492	if (error == 0)
493		return (BUS_PROBE_GENERIC);
494	return (error);
495} /* ubt_probe */
496
497/*
498 * Attach the device.
499 * USB context.
500 */
501
502static int
503ubt_attach(device_t dev)
504{
505	struct usb_attach_arg		*uaa = device_get_ivars(dev);
506	struct ubt_softc		*sc = device_get_softc(dev);
507	struct usb_endpoint_descriptor	*ed;
508	struct usb_interface_descriptor *id;
509	uint16_t			wMaxPacketSize;
510	uint8_t				alt_index, i, j;
511	uint8_t				iface_index[2] = { 0, 1 };
512
513	device_set_usb_desc(dev);
514
515	sc->sc_dev = dev;
516	sc->sc_debug = NG_UBT_WARN_LEVEL;
517
518	/*
519	 * Create Netgraph node
520	 */
521
522	if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
523		UBT_ALERT(sc, "could not create Netgraph node\n");
524		return (ENXIO);
525	}
526
527	/* Name Netgraph node */
528	if (ng_name_node(sc->sc_node, device_get_nameunit(dev)) != 0) {
529		UBT_ALERT(sc, "could not name Netgraph node\n");
530		NG_NODE_UNREF(sc->sc_node);
531		return (ENXIO);
532	}
533	NG_NODE_SET_PRIVATE(sc->sc_node, sc);
534	NG_NODE_FORCE_WRITER(sc->sc_node);
535
536	/*
537	 * Initialize device softc structure
538	 */
539
540	/* initialize locks */
541	mtx_init(&sc->sc_ng_mtx, "ubt ng", NULL, MTX_DEF);
542	mtx_init(&sc->sc_if_mtx, "ubt if", NULL, MTX_DEF | MTX_RECURSE);
543
544	/* initialize packet queues */
545	NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
546	NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
547	NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
548
549	/* initialize glue task */
550	TASK_INIT(&sc->sc_task, 0, ubt_task, sc);
551
552	/*
553	 * Configure Bluetooth USB device. Discover all required USB
554	 * interfaces and endpoints.
555	 *
556	 * USB device must present two interfaces:
557	 * 1) Interface 0 that has 3 endpoints
558	 *	1) Interrupt endpoint to receive HCI events
559	 *	2) Bulk IN endpoint to receive ACL data
560	 *	3) Bulk OUT endpoint to send ACL data
561	 *
562	 * 2) Interface 1 then has 2 endpoints
563	 *	1) Isochronous IN endpoint to receive SCO data
564 	 *	2) Isochronous OUT endpoint to send SCO data
565	 *
566	 * Interface 1 (with isochronous endpoints) has several alternate
567	 * configurations with different packet size.
568	 */
569
570	/*
571	 * For interface #1 search alternate settings, and find
572	 * the descriptor with the largest wMaxPacketSize
573	 */
574
575	wMaxPacketSize = 0;
576	alt_index = 0;
577	i = 0;
578	j = 0;
579	ed = NULL;
580
581	/*
582	 * Search through all the descriptors looking for the largest
583	 * packet size:
584	 */
585	while ((ed = (struct usb_endpoint_descriptor *)usb_desc_foreach(
586	    usbd_get_config_descriptor(uaa->device),
587	    (struct usb_descriptor *)ed))) {
588
589		if ((ed->bDescriptorType == UDESC_INTERFACE) &&
590		    (ed->bLength >= sizeof(*id))) {
591			id = (struct usb_interface_descriptor *)ed;
592			i = id->bInterfaceNumber;
593			j = id->bAlternateSetting;
594		}
595
596		if ((ed->bDescriptorType == UDESC_ENDPOINT) &&
597		    (ed->bLength >= sizeof(*ed)) &&
598		    (i == 1)) {
599			uint16_t temp;
600
601			temp = UGETW(ed->wMaxPacketSize);
602			if (temp > wMaxPacketSize) {
603				wMaxPacketSize = temp;
604				alt_index = j;
605			}
606		}
607	}
608
609	/* Set alt configuration on interface #1 only if we found it */
610	if (wMaxPacketSize > 0 &&
611	    usbd_set_alt_interface_index(uaa->device, 1, alt_index)) {
612		UBT_ALERT(sc, "could not set alternate setting %d " \
613			"for interface 1!\n", alt_index);
614		goto detach;
615	}
616
617	/* Setup transfers for both interfaces */
618	if (usbd_transfer_setup(uaa->device, iface_index, sc->sc_xfer,
619			ubt_config, UBT_N_TRANSFER, sc, &sc->sc_if_mtx)) {
620		UBT_ALERT(sc, "could not allocate transfers\n");
621		goto detach;
622	}
623
624	/* Claim all interfaces on the device */
625	for (i = 1; usbd_get_iface(uaa->device, i) != NULL; i ++)
626		usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex);
627
628	return (0); /* success */
629
630detach:
631	ubt_detach(dev);
632
633	return (ENXIO);
634} /* ubt_attach */
635
636/*
637 * Detach the device.
638 * USB context.
639 */
640
641int
642ubt_detach(device_t dev)
643{
644	struct ubt_softc	*sc = device_get_softc(dev);
645	node_p			node = sc->sc_node;
646
647	/* Destroy Netgraph node */
648	if (node != NULL) {
649		sc->sc_node = NULL;
650		NG_NODE_REALLY_DIE(node);
651		ng_rmnode_self(node);
652	}
653
654	/* Make sure ubt_task in gone */
655	taskqueue_drain(taskqueue_swi, &sc->sc_task);
656
657	/* Free USB transfers, if any */
658	usbd_transfer_unsetup(sc->sc_xfer, UBT_N_TRANSFER);
659
660	/* Destroy queues */
661	UBT_NG_LOCK(sc);
662	NG_BT_MBUFQ_DESTROY(&sc->sc_cmdq);
663	NG_BT_MBUFQ_DESTROY(&sc->sc_aclq);
664	NG_BT_MBUFQ_DESTROY(&sc->sc_scoq);
665	UBT_NG_UNLOCK(sc);
666
667	mtx_destroy(&sc->sc_if_mtx);
668	mtx_destroy(&sc->sc_ng_mtx);
669
670	return (0);
671} /* ubt_detach */
672
673/*
674 * Called when outgoing control request (HCI command) has completed, i.e.
675 * HCI command was sent to the device.
676 * USB context.
677 */
678
679static void
680ubt_ctrl_write_callback(struct usb_xfer *xfer, usb_error_t error)
681{
682	struct ubt_softc		*sc = usbd_xfer_softc(xfer);
683	struct usb_device_request	req;
684	struct mbuf			*m;
685	struct usb_page_cache		*pc;
686	int				actlen;
687
688	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
689
690	switch (USB_GET_STATE(xfer)) {
691	case USB_ST_TRANSFERRED:
692		UBT_INFO(sc, "sent %d bytes to control pipe\n", actlen);
693		UBT_STAT_BYTES_SENT(sc, actlen);
694		UBT_STAT_PCKTS_SENT(sc);
695		/* FALLTHROUGH */
696
697	case USB_ST_SETUP:
698send_next:
699		/* Get next command mbuf, if any */
700		UBT_NG_LOCK(sc);
701		NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
702		UBT_NG_UNLOCK(sc);
703
704		if (m == NULL) {
705			UBT_INFO(sc, "HCI command queue is empty\n");
706			break;	/* transfer complete */
707		}
708
709		/* Initialize a USB control request and then schedule it */
710		bzero(&req, sizeof(req));
711		req.bmRequestType = UBT_HCI_REQUEST;
712		USETW(req.wLength, m->m_pkthdr.len);
713
714		UBT_INFO(sc, "Sending control request, " \
715			"bmRequestType=0x%02x, wLength=%d\n",
716			req.bmRequestType, UGETW(req.wLength));
717
718		pc = usbd_xfer_get_frame(xfer, 0);
719		usbd_copy_in(pc, 0, &req, sizeof(req));
720		pc = usbd_xfer_get_frame(xfer, 1);
721		usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len);
722
723		usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
724		usbd_xfer_set_frame_len(xfer, 1, m->m_pkthdr.len);
725		usbd_xfer_set_frames(xfer, 2);
726
727		NG_FREE_M(m);
728
729		usbd_transfer_submit(xfer);
730		break;
731
732	default: /* Error */
733		if (error != USB_ERR_CANCELLED) {
734			UBT_WARN(sc, "control transfer failed: %s\n",
735				usbd_errstr(error));
736
737			UBT_STAT_OERROR(sc);
738			goto send_next;
739		}
740
741		/* transfer cancelled */
742		break;
743	}
744} /* ubt_ctrl_write_callback */
745
746/*
747 * Called when incoming interrupt transfer (HCI event) has completed, i.e.
748 * HCI event was received from the device.
749 * USB context.
750 */
751
752static void
753ubt_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
754{
755	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
756	struct mbuf		*m;
757	ng_hci_event_pkt_t	*hdr;
758	struct usb_page_cache	*pc;
759	int			actlen;
760
761	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
762
763	m = NULL;
764
765	switch (USB_GET_STATE(xfer)) {
766	case USB_ST_TRANSFERRED:
767		/* Allocate a new mbuf */
768		MGETHDR(m, M_DONTWAIT, MT_DATA);
769		if (m == NULL) {
770			UBT_STAT_IERROR(sc);
771			goto submit_next;
772		}
773
774		MCLGET(m, M_DONTWAIT);
775		if (!(m->m_flags & M_EXT)) {
776			UBT_STAT_IERROR(sc);
777			goto submit_next;
778		}
779
780		/* Add HCI packet type */
781		*mtod(m, uint8_t *)= NG_HCI_EVENT_PKT;
782		m->m_pkthdr.len = m->m_len = 1;
783
784		if (actlen > MCLBYTES - 1)
785			actlen = MCLBYTES - 1;
786
787		pc = usbd_xfer_get_frame(xfer, 0);
788		usbd_copy_out(pc, 0, mtod(m, uint8_t *) + 1, actlen);
789		m->m_pkthdr.len += actlen;
790		m->m_len += actlen;
791
792		UBT_INFO(sc, "got %d bytes from interrupt pipe\n",
793			actlen);
794
795		/* Validate packet and send it up the stack */
796		if (m->m_pkthdr.len < (int)sizeof(*hdr)) {
797			UBT_INFO(sc, "HCI event packet is too short\n");
798
799			UBT_STAT_IERROR(sc);
800			goto submit_next;
801		}
802
803		hdr = mtod(m, ng_hci_event_pkt_t *);
804		if (hdr->length != (m->m_pkthdr.len - sizeof(*hdr))) {
805			UBT_ERR(sc, "Invalid HCI event packet size, " \
806				"length=%d, pktlen=%d\n",
807				hdr->length, m->m_pkthdr.len);
808
809			UBT_STAT_IERROR(sc);
810			goto submit_next;
811		}
812
813		UBT_INFO(sc, "got complete HCI event frame, pktlen=%d, " \
814			"length=%d\n", m->m_pkthdr.len, hdr->length);
815
816		UBT_STAT_PCKTS_RECV(sc);
817		UBT_STAT_BYTES_RECV(sc, m->m_pkthdr.len);
818
819		ubt_fwd_mbuf_up(sc, &m);
820		/* m == NULL at this point */
821		/* FALLTHROUGH */
822
823	case USB_ST_SETUP:
824submit_next:
825		NG_FREE_M(m); /* checks for m != NULL */
826
827		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
828		usbd_transfer_submit(xfer);
829		break;
830
831	default: /* Error */
832		if (error != USB_ERR_CANCELLED) {
833			UBT_WARN(sc, "interrupt transfer failed: %s\n",
834				usbd_errstr(error));
835
836			/* Try to clear stall first */
837			usbd_xfer_set_stall(xfer);
838			goto submit_next;
839		}
840			/* transfer cancelled */
841		break;
842	}
843} /* ubt_intr_read_callback */
844
845/*
846 * Called when incoming bulk transfer (ACL packet) has completed, i.e.
847 * ACL packet was received from the device.
848 * USB context.
849 */
850
851static void
852ubt_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
853{
854	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
855	struct mbuf		*m;
856	ng_hci_acldata_pkt_t	*hdr;
857	struct usb_page_cache	*pc;
858	int len;
859	int actlen;
860
861	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
862
863	m = NULL;
864
865	switch (USB_GET_STATE(xfer)) {
866	case USB_ST_TRANSFERRED:
867		/* Allocate new mbuf */
868		MGETHDR(m, M_DONTWAIT, MT_DATA);
869		if (m == NULL) {
870			UBT_STAT_IERROR(sc);
871			goto submit_next;
872		}
873
874		MCLGET(m, M_DONTWAIT);
875		if (!(m->m_flags & M_EXT)) {
876			UBT_STAT_IERROR(sc);
877			goto submit_next;
878		}
879
880		/* Add HCI packet type */
881		*mtod(m, uint8_t *)= NG_HCI_ACL_DATA_PKT;
882		m->m_pkthdr.len = m->m_len = 1;
883
884		if (actlen > MCLBYTES - 1)
885			actlen = MCLBYTES - 1;
886
887		pc = usbd_xfer_get_frame(xfer, 0);
888		usbd_copy_out(pc, 0, mtod(m, uint8_t *) + 1, actlen);
889		m->m_pkthdr.len += actlen;
890		m->m_len += actlen;
891
892		UBT_INFO(sc, "got %d bytes from bulk-in pipe\n",
893			actlen);
894
895		/* Validate packet and send it up the stack */
896		if (m->m_pkthdr.len < (int)sizeof(*hdr)) {
897			UBT_INFO(sc, "HCI ACL packet is too short\n");
898
899			UBT_STAT_IERROR(sc);
900			goto submit_next;
901		}
902
903		hdr = mtod(m, ng_hci_acldata_pkt_t *);
904		len = le16toh(hdr->length);
905		if (len != (int)(m->m_pkthdr.len - sizeof(*hdr))) {
906			UBT_ERR(sc, "Invalid ACL packet size, length=%d, " \
907				"pktlen=%d\n", len, m->m_pkthdr.len);
908
909			UBT_STAT_IERROR(sc);
910			goto submit_next;
911		}
912
913		UBT_INFO(sc, "got complete ACL data packet, pktlen=%d, " \
914			"length=%d\n", m->m_pkthdr.len, len);
915
916		UBT_STAT_PCKTS_RECV(sc);
917		UBT_STAT_BYTES_RECV(sc, m->m_pkthdr.len);
918
919		ubt_fwd_mbuf_up(sc, &m);
920		/* m == NULL at this point */
921		/* FALLTHOUGH */
922
923	case USB_ST_SETUP:
924submit_next:
925		NG_FREE_M(m); /* checks for m != NULL */
926
927		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
928		usbd_transfer_submit(xfer);
929		break;
930
931	default: /* Error */
932		if (error != USB_ERR_CANCELLED) {
933			UBT_WARN(sc, "bulk-in transfer failed: %s\n",
934				usbd_errstr(error));
935
936			/* Try to clear stall first */
937			usbd_xfer_set_stall(xfer);
938			goto submit_next;
939		}
940			/* transfer cancelled */
941		break;
942	}
943} /* ubt_bulk_read_callback */
944
945/*
946 * Called when outgoing bulk transfer (ACL packet) has completed, i.e.
947 * ACL packet was sent to the device.
948 * USB context.
949 */
950
951static void
952ubt_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
953{
954	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
955	struct mbuf		*m;
956	struct usb_page_cache	*pc;
957	int			actlen;
958
959	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
960
961	switch (USB_GET_STATE(xfer)) {
962	case USB_ST_TRANSFERRED:
963		UBT_INFO(sc, "sent %d bytes to bulk-out pipe\n", actlen);
964		UBT_STAT_BYTES_SENT(sc, actlen);
965		UBT_STAT_PCKTS_SENT(sc);
966		/* FALLTHROUGH */
967
968	case USB_ST_SETUP:
969send_next:
970		/* Get next mbuf, if any */
971		UBT_NG_LOCK(sc);
972		NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
973		UBT_NG_UNLOCK(sc);
974
975		if (m == NULL) {
976			UBT_INFO(sc, "ACL data queue is empty\n");
977			break; /* transfer completed */
978		}
979
980		/*
981		 * Copy ACL data frame back to a linear USB transfer buffer
982		 * and schedule transfer
983		 */
984
985		pc = usbd_xfer_get_frame(xfer, 0);
986		usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len);
987		usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len);
988
989		UBT_INFO(sc, "bulk-out transfer has been started, len=%d\n",
990			m->m_pkthdr.len);
991
992		NG_FREE_M(m);
993
994		usbd_transfer_submit(xfer);
995		break;
996
997	default: /* Error */
998		if (error != USB_ERR_CANCELLED) {
999			UBT_WARN(sc, "bulk-out transfer failed: %s\n",
1000				usbd_errstr(error));
1001
1002			UBT_STAT_OERROR(sc);
1003
1004			/* try to clear stall first */
1005			usbd_xfer_set_stall(xfer);
1006			goto send_next;
1007		}
1008			/* transfer cancelled */
1009		break;
1010	}
1011} /* ubt_bulk_write_callback */
1012
1013/*
1014 * Called when incoming isoc transfer (SCO packet) has completed, i.e.
1015 * SCO packet was received from the device.
1016 * USB context.
1017 */
1018
1019static void
1020ubt_isoc_read_callback(struct usb_xfer *xfer, usb_error_t error)
1021{
1022	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
1023	int			n;
1024	int actlen, nframes;
1025
1026	usbd_xfer_status(xfer, &actlen, NULL, NULL, &nframes);
1027
1028	switch (USB_GET_STATE(xfer)) {
1029	case USB_ST_TRANSFERRED:
1030		for (n = 0; n < nframes; n ++)
1031			if (ubt_isoc_read_one_frame(xfer, n) < 0)
1032				break;
1033		/* FALLTHROUGH */
1034
1035	case USB_ST_SETUP:
1036read_next:
1037		for (n = 0; n < nframes; n ++)
1038			usbd_xfer_set_frame_len(xfer, n,
1039			    usbd_xfer_max_framelen(xfer));
1040
1041		usbd_transfer_submit(xfer);
1042		break;
1043
1044	default: /* Error */
1045                if (error != USB_ERR_CANCELLED) {
1046                        UBT_STAT_IERROR(sc);
1047                        goto read_next;
1048                }
1049
1050		/* transfer cancelled */
1051		break;
1052	}
1053} /* ubt_isoc_read_callback */
1054
1055/*
1056 * Helper function. Called from ubt_isoc_read_callback() to read
1057 * SCO data from one frame.
1058 * USB context.
1059 */
1060
1061static int
1062ubt_isoc_read_one_frame(struct usb_xfer *xfer, int frame_no)
1063{
1064	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
1065	struct usb_page_cache	*pc;
1066	struct mbuf		*m;
1067	int			len, want, got, total;
1068
1069	/* Get existing SCO reassembly buffer */
1070	pc = usbd_xfer_get_frame(xfer, 0);
1071	m = sc->sc_isoc_in_buffer;
1072	total = usbd_xfer_frame_len(xfer, frame_no);
1073
1074	/* While we have data in the frame */
1075	while (total > 0) {
1076		if (m == NULL) {
1077			/* Start new reassembly buffer */
1078			MGETHDR(m, M_DONTWAIT, MT_DATA);
1079			if (m == NULL) {
1080				UBT_STAT_IERROR(sc);
1081				return (-1);	/* XXX out of sync! */
1082			}
1083
1084			MCLGET(m, M_DONTWAIT);
1085			if (!(m->m_flags & M_EXT)) {
1086				UBT_STAT_IERROR(sc);
1087				NG_FREE_M(m);
1088				return (-1);	/* XXX out of sync! */
1089			}
1090
1091			/* Expect SCO header */
1092			*mtod(m, uint8_t *) = NG_HCI_SCO_DATA_PKT;
1093			m->m_pkthdr.len = m->m_len = got = 1;
1094			want = sizeof(ng_hci_scodata_pkt_t);
1095		} else {
1096			/*
1097			 * Check if we have SCO header and if so
1098			 * adjust amount of data we want
1099			 */
1100			got = m->m_pkthdr.len;
1101			want = sizeof(ng_hci_scodata_pkt_t);
1102
1103			if (got >= want)
1104				want += mtod(m, ng_hci_scodata_pkt_t *)->length;
1105		}
1106
1107		/* Append frame data to the SCO reassembly buffer */
1108		len = total;
1109		if (got + len > want)
1110			len = want - got;
1111
1112		usbd_copy_out(pc, frame_no * usbd_xfer_max_framelen(xfer),
1113			mtod(m, uint8_t *) + m->m_pkthdr.len, len);
1114
1115		m->m_pkthdr.len += len;
1116		m->m_len += len;
1117		total -= len;
1118
1119		/* Check if we got everything we wanted, if not - continue */
1120		if (got != want)
1121			continue;
1122
1123		/* If we got here then we got complete SCO frame */
1124		UBT_INFO(sc, "got complete SCO data frame, pktlen=%d, " \
1125			"length=%d\n", m->m_pkthdr.len,
1126			mtod(m, ng_hci_scodata_pkt_t *)->length);
1127
1128		UBT_STAT_PCKTS_RECV(sc);
1129		UBT_STAT_BYTES_RECV(sc, m->m_pkthdr.len);
1130
1131		ubt_fwd_mbuf_up(sc, &m);
1132		/* m == NULL at this point */
1133	}
1134
1135	/* Put SCO reassembly buffer back */
1136	sc->sc_isoc_in_buffer = m;
1137
1138	return (0);
1139} /* ubt_isoc_read_one_frame */
1140
1141/*
1142 * Called when outgoing isoc transfer (SCO packet) has completed, i.e.
1143 * SCO packet was sent to the device.
1144 * USB context.
1145 */
1146
1147static void
1148ubt_isoc_write_callback(struct usb_xfer *xfer, usb_error_t error)
1149{
1150	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
1151	struct usb_page_cache	*pc;
1152	struct mbuf		*m;
1153	int			n, space, offset;
1154	int			actlen, nframes;
1155
1156	usbd_xfer_status(xfer, &actlen, NULL, NULL, &nframes);
1157	pc = usbd_xfer_get_frame(xfer, 0);
1158
1159	switch (USB_GET_STATE(xfer)) {
1160	case USB_ST_TRANSFERRED:
1161		UBT_INFO(sc, "sent %d bytes to isoc-out pipe\n", actlen);
1162		UBT_STAT_BYTES_SENT(sc, actlen);
1163		UBT_STAT_PCKTS_SENT(sc);
1164		/* FALLTHROUGH */
1165
1166	case USB_ST_SETUP:
1167send_next:
1168		offset = 0;
1169		space = usbd_xfer_max_framelen(xfer) * nframes;
1170		m = NULL;
1171
1172		while (space > 0) {
1173			if (m == NULL) {
1174				UBT_NG_LOCK(sc);
1175				NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1176				UBT_NG_UNLOCK(sc);
1177
1178				if (m == NULL)
1179					break;
1180			}
1181
1182			n = min(space, m->m_pkthdr.len);
1183			if (n > 0) {
1184				usbd_m_copy_in(pc, offset, m,0, n);
1185				m_adj(m, n);
1186
1187				offset += n;
1188				space -= n;
1189			}
1190
1191			if (m->m_pkthdr.len == 0)
1192				NG_FREE_M(m); /* sets m = NULL */
1193		}
1194
1195		/* Put whatever is left from mbuf back on queue */
1196		if (m != NULL) {
1197			UBT_NG_LOCK(sc);
1198			NG_BT_MBUFQ_PREPEND(&sc->sc_scoq, m);
1199			UBT_NG_UNLOCK(sc);
1200		}
1201
1202		/*
1203		 * Calculate sizes for isoc frames.
1204		 * Note that offset could be 0 at this point (i.e. we have
1205		 * nothing to send). That is fine, as we have isoc. transfers
1206		 * going in both directions all the time. In this case it
1207		 * would be just empty isoc. transfer.
1208		 */
1209
1210		for (n = 0; n < nframes; n ++) {
1211			usbd_xfer_set_frame_len(xfer, n,
1212			    min(offset, usbd_xfer_max_framelen(xfer)));
1213			offset -= usbd_xfer_frame_len(xfer, n);
1214		}
1215
1216		usbd_transfer_submit(xfer);
1217		break;
1218
1219	default: /* Error */
1220		if (error != USB_ERR_CANCELLED) {
1221			UBT_STAT_OERROR(sc);
1222			goto send_next;
1223		}
1224
1225		/* transfer cancelled */
1226		break;
1227	}
1228}
1229
1230/*
1231 * Utility function to forward provided mbuf upstream (i.e. up the stack).
1232 * Modifies value of the mbuf pointer (sets it to NULL).
1233 * Save to call from any context.
1234 */
1235
1236static int
1237ubt_fwd_mbuf_up(ubt_softc_p sc, struct mbuf **m)
1238{
1239	hook_p	hook;
1240	int	error;
1241
1242	/*
1243	 * Close the race with Netgraph hook newhook/disconnect methods.
1244	 * Save the hook pointer atomically. Two cases are possible:
1245	 *
1246	 * 1) The hook pointer is NULL. It means disconnect method got
1247	 *    there first. In this case we are done.
1248	 *
1249	 * 2) The hook pointer is not NULL. It means that hook pointer
1250	 *    could be either in valid or invalid (i.e. in the process
1251	 *    of disconnect) state. In any case grab an extra reference
1252	 *    to protect the hook pointer.
1253	 *
1254	 * It is ok to pass hook in invalid state to NG_SEND_DATA_ONLY() as
1255	 * it checks for it. Drop extra reference after NG_SEND_DATA_ONLY().
1256	 */
1257
1258	UBT_NG_LOCK(sc);
1259	if ((hook = sc->sc_hook) != NULL)
1260		NG_HOOK_REF(hook);
1261	UBT_NG_UNLOCK(sc);
1262
1263	if (hook == NULL) {
1264		NG_FREE_M(*m);
1265		return (ENETDOWN);
1266	}
1267
1268	NG_SEND_DATA_ONLY(error, hook, *m);
1269	NG_HOOK_UNREF(hook);
1270
1271	if (error != 0)
1272		UBT_STAT_IERROR(sc);
1273
1274	return (error);
1275} /* ubt_fwd_mbuf_up */
1276
1277/****************************************************************************
1278 ****************************************************************************
1279 **                                 Glue
1280 ****************************************************************************
1281 ****************************************************************************/
1282
1283/*
1284 * Schedule glue task. Should be called with sc_ng_mtx held.
1285 * Netgraph context.
1286 */
1287
1288static void
1289ubt_task_schedule(ubt_softc_p sc, int action)
1290{
1291	mtx_assert(&sc->sc_ng_mtx, MA_OWNED);
1292
1293	/*
1294	 * Try to handle corner case when "start all" and "stop all"
1295	 * actions can both be set before task is executed.
1296	 *
1297	 * The rules are
1298	 *
1299	 * sc_task_flags	action		new sc_task_flags
1300	 * ------------------------------------------------------
1301	 * 0			start		start
1302	 * 0			stop		stop
1303	 * start		start		start
1304	 * start		stop		stop
1305	 * stop			start		stop|start
1306	 * stop			stop		stop
1307	 * stop|start		start		stop|start
1308	 * stop|start		stop		stop
1309	 */
1310
1311	if (action != 0) {
1312		if ((action & UBT_FLAG_T_STOP_ALL) != 0)
1313			sc->sc_task_flags &= ~UBT_FLAG_T_START_ALL;
1314
1315		sc->sc_task_flags |= action;
1316	}
1317
1318	if (sc->sc_task_flags & UBT_FLAG_T_PENDING)
1319		return;
1320
1321	if (taskqueue_enqueue(taskqueue_swi, &sc->sc_task) == 0) {
1322		sc->sc_task_flags |= UBT_FLAG_T_PENDING;
1323		return;
1324	}
1325
1326	/* XXX: i think this should never happen */
1327} /* ubt_task_schedule */
1328
1329/*
1330 * Glue task. Examines sc_task_flags and does things depending on it.
1331 * Taskqueue context.
1332 */
1333
1334static void
1335ubt_task(void *context, int pending)
1336{
1337	ubt_softc_p	sc = context;
1338	int		task_flags, i;
1339
1340	UBT_NG_LOCK(sc);
1341	task_flags = sc->sc_task_flags;
1342	sc->sc_task_flags = 0;
1343	UBT_NG_UNLOCK(sc);
1344
1345	/*
1346	 * Stop all USB transfers synchronously.
1347	 * Stop interface #0 and #1 transfers at the same time and in the
1348	 * same loop. usbd_transfer_drain() will do appropriate locking.
1349	 */
1350
1351	if (task_flags & UBT_FLAG_T_STOP_ALL)
1352		for (i = 0; i < UBT_N_TRANSFER; i ++)
1353			usbd_transfer_drain(sc->sc_xfer[i]);
1354
1355	/* Start incoming interrupt and bulk, and all isoc. USB transfers */
1356	if (task_flags & UBT_FLAG_T_START_ALL) {
1357		/*
1358		 * Interface #0
1359		 */
1360
1361		mtx_lock(&sc->sc_if_mtx);
1362
1363		ubt_xfer_start(sc, UBT_IF_0_INTR_DT_RD);
1364		ubt_xfer_start(sc, UBT_IF_0_BULK_DT_RD);
1365
1366		/*
1367		 * Interface #1
1368		 * Start both read and write isoc. transfers by default.
1369		 * Get them going all the time even if we have nothing
1370		 * to send to avoid any delays.
1371		 */
1372
1373		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_RD1);
1374		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_RD2);
1375		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_WR1);
1376		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_WR2);
1377
1378		mtx_unlock(&sc->sc_if_mtx);
1379	}
1380
1381 	/* Start outgoing control transfer */
1382	if (task_flags & UBT_FLAG_T_START_CTRL) {
1383		mtx_lock(&sc->sc_if_mtx);
1384		ubt_xfer_start(sc, UBT_IF_0_CTRL_DT_WR);
1385		mtx_unlock(&sc->sc_if_mtx);
1386	}
1387
1388	/* Start outgoing bulk transfer */
1389	if (task_flags & UBT_FLAG_T_START_BULK) {
1390		mtx_lock(&sc->sc_if_mtx);
1391		ubt_xfer_start(sc, UBT_IF_0_BULK_DT_WR);
1392		mtx_unlock(&sc->sc_if_mtx);
1393	}
1394} /* ubt_task */
1395
1396/****************************************************************************
1397 ****************************************************************************
1398 **                        Netgraph specific
1399 ****************************************************************************
1400 ****************************************************************************/
1401
1402/*
1403 * Netgraph node constructor. Do not allow to create node of this type.
1404 * Netgraph context.
1405 */
1406
1407static int
1408ng_ubt_constructor(node_p node)
1409{
1410	return (EINVAL);
1411} /* ng_ubt_constructor */
1412
1413/*
1414 * Netgraph node destructor. Destroy node only when device has been detached.
1415 * Netgraph context.
1416 */
1417
1418static int
1419ng_ubt_shutdown(node_p node)
1420{
1421	if (node->nd_flags & NGF_REALLY_DIE) {
1422		/*
1423                 * We came here because the USB device is being
1424		 * detached, so stop being persistant.
1425                 */
1426		NG_NODE_SET_PRIVATE(node, NULL);
1427		NG_NODE_UNREF(node);
1428	} else
1429		NG_NODE_REVIVE(node); /* tell ng_rmnode we are persisant */
1430
1431	return (0);
1432} /* ng_ubt_shutdown */
1433
1434/*
1435 * Create new hook. There can only be one.
1436 * Netgraph context.
1437 */
1438
1439static int
1440ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1441{
1442	struct ubt_softc	*sc = NG_NODE_PRIVATE(node);
1443
1444	if (strcmp(name, NG_UBT_HOOK) != 0)
1445		return (EINVAL);
1446
1447	UBT_NG_LOCK(sc);
1448	if (sc->sc_hook != NULL) {
1449		UBT_NG_UNLOCK(sc);
1450
1451		return (EISCONN);
1452	}
1453
1454	sc->sc_hook = hook;
1455	UBT_NG_UNLOCK(sc);
1456
1457	return (0);
1458} /* ng_ubt_newhook */
1459
1460/*
1461 * Connect hook. Start incoming USB transfers.
1462 * Netgraph context.
1463 */
1464
1465static int
1466ng_ubt_connect(hook_p hook)
1467{
1468	struct ubt_softc	*sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1469
1470	NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1471
1472	UBT_NG_LOCK(sc);
1473	ubt_task_schedule(sc, UBT_FLAG_T_START_ALL);
1474	UBT_NG_UNLOCK(sc);
1475
1476	return (0);
1477} /* ng_ubt_connect */
1478
1479/*
1480 * Disconnect hook.
1481 * Netgraph context.
1482 */
1483
1484static int
1485ng_ubt_disconnect(hook_p hook)
1486{
1487	struct ubt_softc	*sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1488
1489	UBT_NG_LOCK(sc);
1490
1491	if (hook != sc->sc_hook) {
1492		UBT_NG_UNLOCK(sc);
1493
1494		return (EINVAL);
1495	}
1496
1497	sc->sc_hook = NULL;
1498
1499	/* Kick off task to stop all USB xfers */
1500	ubt_task_schedule(sc, UBT_FLAG_T_STOP_ALL);
1501
1502	/* Drain queues */
1503	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1504	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1505	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1506
1507	UBT_NG_UNLOCK(sc);
1508
1509	return (0);
1510} /* ng_ubt_disconnect */
1511
1512/*
1513 * Process control message.
1514 * Netgraph context.
1515 */
1516
1517static int
1518ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
1519{
1520	struct ubt_softc	*sc = NG_NODE_PRIVATE(node);
1521	struct ng_mesg		*msg, *rsp = NULL;
1522	struct ng_bt_mbufq	*q;
1523	int			error = 0, queue, qlen;
1524
1525	NGI_GET_MSG(item, msg);
1526
1527	switch (msg->header.typecookie) {
1528	case NGM_GENERIC_COOKIE:
1529		switch (msg->header.cmd) {
1530		case NGM_TEXT_STATUS:
1531			NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
1532			if (rsp == NULL) {
1533				error = ENOMEM;
1534				break;
1535			}
1536
1537			snprintf(rsp->data, NG_TEXTRESPONSE,
1538				"Hook: %s\n" \
1539				"Task flags: %#x\n" \
1540				"Debug: %d\n" \
1541				"CMD queue: [have:%d,max:%d]\n" \
1542				"ACL queue: [have:%d,max:%d]\n" \
1543				"SCO queue: [have:%d,max:%d]",
1544				(sc->sc_hook != NULL) ? NG_UBT_HOOK : "",
1545				sc->sc_task_flags,
1546				sc->sc_debug,
1547				sc->sc_cmdq.len,
1548				sc->sc_cmdq.maxlen,
1549				sc->sc_aclq.len,
1550				sc->sc_aclq.maxlen,
1551				sc->sc_scoq.len,
1552				sc->sc_scoq.maxlen);
1553			break;
1554
1555		default:
1556			error = EINVAL;
1557			break;
1558		}
1559		break;
1560
1561	case NGM_UBT_COOKIE:
1562		switch (msg->header.cmd) {
1563		case NGM_UBT_NODE_SET_DEBUG:
1564			if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep)){
1565				error = EMSGSIZE;
1566				break;
1567			}
1568
1569			sc->sc_debug = *((ng_ubt_node_debug_ep *) (msg->data));
1570			break;
1571
1572		case NGM_UBT_NODE_GET_DEBUG:
1573			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
1574			    M_NOWAIT);
1575			if (rsp == NULL) {
1576				error = ENOMEM;
1577				break;
1578			}
1579
1580			*((ng_ubt_node_debug_ep *) (rsp->data)) = sc->sc_debug;
1581			break;
1582
1583		case NGM_UBT_NODE_SET_QLEN:
1584			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
1585				error = EMSGSIZE;
1586				break;
1587			}
1588
1589			queue = ((ng_ubt_node_qlen_ep *) (msg->data))->queue;
1590			qlen = ((ng_ubt_node_qlen_ep *) (msg->data))->qlen;
1591
1592			switch (queue) {
1593			case NGM_UBT_NODE_QUEUE_CMD:
1594				q = &sc->sc_cmdq;
1595				break;
1596
1597			case NGM_UBT_NODE_QUEUE_ACL:
1598				q = &sc->sc_aclq;
1599				break;
1600
1601			case NGM_UBT_NODE_QUEUE_SCO:
1602				q = &sc->sc_scoq;
1603				break;
1604
1605			default:
1606				error = EINVAL;
1607				goto done;
1608				/* NOT REACHED */
1609			}
1610
1611			q->maxlen = qlen;
1612			break;
1613
1614		case NGM_UBT_NODE_GET_QLEN:
1615			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
1616				error = EMSGSIZE;
1617				break;
1618			}
1619
1620			queue = ((ng_ubt_node_qlen_ep *) (msg->data))->queue;
1621
1622			switch (queue) {
1623			case NGM_UBT_NODE_QUEUE_CMD:
1624				q = &sc->sc_cmdq;
1625				break;
1626
1627			case NGM_UBT_NODE_QUEUE_ACL:
1628				q = &sc->sc_aclq;
1629				break;
1630
1631			case NGM_UBT_NODE_QUEUE_SCO:
1632				q = &sc->sc_scoq;
1633				break;
1634
1635			default:
1636				error = EINVAL;
1637				goto done;
1638				/* NOT REACHED */
1639			}
1640
1641			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_qlen_ep),
1642				M_NOWAIT);
1643			if (rsp == NULL) {
1644				error = ENOMEM;
1645				break;
1646			}
1647
1648			((ng_ubt_node_qlen_ep *) (rsp->data))->queue = queue;
1649			((ng_ubt_node_qlen_ep *) (rsp->data))->qlen = q->maxlen;
1650			break;
1651
1652		case NGM_UBT_NODE_GET_STAT:
1653			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
1654			    M_NOWAIT);
1655			if (rsp == NULL) {
1656				error = ENOMEM;
1657				break;
1658			}
1659
1660			bcopy(&sc->sc_stat, rsp->data,
1661				sizeof(ng_ubt_node_stat_ep));
1662			break;
1663
1664		case NGM_UBT_NODE_RESET_STAT:
1665			UBT_STAT_RESET(sc);
1666			break;
1667
1668		default:
1669			error = EINVAL;
1670			break;
1671		}
1672		break;
1673
1674	default:
1675		error = EINVAL;
1676		break;
1677	}
1678done:
1679	NG_RESPOND_MSG(error, node, item, rsp);
1680	NG_FREE_MSG(msg);
1681
1682	return (error);
1683} /* ng_ubt_rcvmsg */
1684
1685/*
1686 * Process data.
1687 * Netgraph context.
1688 */
1689
1690static int
1691ng_ubt_rcvdata(hook_p hook, item_p item)
1692{
1693	struct ubt_softc	*sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1694	struct mbuf		*m;
1695	struct ng_bt_mbufq	*q;
1696	int			action, error = 0;
1697
1698	if (hook != sc->sc_hook) {
1699		error = EINVAL;
1700		goto done;
1701	}
1702
1703	/* Deatch mbuf and get HCI frame type */
1704	NGI_GET_M(item, m);
1705
1706	/*
1707	 * Minimal size of the HCI frame is 4 bytes: 1 byte frame type,
1708	 * 2 bytes connection handle and at least 1 byte of length.
1709	 * Panic on data frame that has size smaller than 4 bytes (it
1710	 * should not happen)
1711	 */
1712
1713	if (m->m_pkthdr.len < 4)
1714		panic("HCI frame size is too small! pktlen=%d\n",
1715			m->m_pkthdr.len);
1716
1717	/* Process HCI frame */
1718	switch (*mtod(m, uint8_t *)) {	/* XXX call m_pullup ? */
1719	case NG_HCI_CMD_PKT:
1720		if (m->m_pkthdr.len - 1 > (int)UBT_CTRL_BUFFER_SIZE)
1721			panic("HCI command frame size is too big! " \
1722				"buffer size=%zd, packet len=%d\n",
1723				UBT_CTRL_BUFFER_SIZE, m->m_pkthdr.len);
1724
1725		q = &sc->sc_cmdq;
1726		action = UBT_FLAG_T_START_CTRL;
1727		break;
1728
1729	case NG_HCI_ACL_DATA_PKT:
1730		if (m->m_pkthdr.len - 1 > UBT_BULK_WRITE_BUFFER_SIZE)
1731			panic("ACL data frame size is too big! " \
1732				"buffer size=%d, packet len=%d\n",
1733				UBT_BULK_WRITE_BUFFER_SIZE, m->m_pkthdr.len);
1734
1735		q = &sc->sc_aclq;
1736		action = UBT_FLAG_T_START_BULK;
1737		break;
1738
1739	case NG_HCI_SCO_DATA_PKT:
1740		q = &sc->sc_scoq;
1741		action = 0;
1742		break;
1743
1744	default:
1745		UBT_ERR(sc, "Dropping unsupported HCI frame, type=0x%02x, " \
1746			"pktlen=%d\n", *mtod(m, uint8_t *), m->m_pkthdr.len);
1747
1748		NG_FREE_M(m);
1749		error = EINVAL;
1750		goto done;
1751		/* NOT REACHED */
1752	}
1753
1754	UBT_NG_LOCK(sc);
1755	if (NG_BT_MBUFQ_FULL(q)) {
1756		NG_BT_MBUFQ_DROP(q);
1757		UBT_NG_UNLOCK(sc);
1758
1759		UBT_ERR(sc, "Dropping HCI frame 0x%02x, len=%d. Queue full\n",
1760			*mtod(m, uint8_t *), m->m_pkthdr.len);
1761
1762		NG_FREE_M(m);
1763	} else {
1764		/* Loose HCI packet type, enqueue mbuf and kick off task */
1765		m_adj(m, sizeof(uint8_t));
1766		NG_BT_MBUFQ_ENQUEUE(q, m);
1767		ubt_task_schedule(sc, action);
1768		UBT_NG_UNLOCK(sc);
1769	}
1770done:
1771	NG_FREE_ITEM(item);
1772
1773	return (error);
1774} /* ng_ubt_rcvdata */
1775
1776/****************************************************************************
1777 ****************************************************************************
1778 **                              Module
1779 ****************************************************************************
1780 ****************************************************************************/
1781
1782/*
1783 * Load/Unload the driver module
1784 */
1785
1786static int
1787ubt_modevent(module_t mod, int event, void *data)
1788{
1789	int	error;
1790
1791	switch (event) {
1792	case MOD_LOAD:
1793		error = ng_newtype(&typestruct);
1794		if (error != 0)
1795			printf("%s: Could not register Netgraph node type, " \
1796				"error=%d\n", NG_UBT_NODE_TYPE, error);
1797		break;
1798
1799	case MOD_UNLOAD:
1800		error = ng_rmtype(&typestruct);
1801		break;
1802
1803	default:
1804		error = EOPNOTSUPP;
1805		break;
1806	}
1807
1808	return (error);
1809} /* ubt_modevent */
1810
1811static devclass_t	ubt_devclass;
1812
1813static device_method_t	ubt_methods[] =
1814{
1815	DEVMETHOD(device_probe,	ubt_probe),
1816	DEVMETHOD(device_attach, ubt_attach),
1817	DEVMETHOD(device_detach, ubt_detach),
1818	DEVMETHOD_END
1819};
1820
1821static driver_t		ubt_driver =
1822{
1823	.name =	   "ubt",
1824	.methods = ubt_methods,
1825	.size =	   sizeof(struct ubt_softc),
1826};
1827
1828DRIVER_MODULE(ng_ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
1829MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
1830MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
1831MODULE_DEPEND(ng_ubt, ng_hci, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION);
1832MODULE_DEPEND(ng_ubt, usb, 1, 1, 1);
1833
1834