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