xref: /freebsd-14-stable/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c (revision e908df969af2384def482c0629ce1c83c018b415)
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 
448 /* List of supported bluetooth devices */
449 static const STRUCT_USB_HOST_ID ubt_devs[] =
450 {
451 	/* Generic Bluetooth class devices */
452 	{ USB_IFACE_CLASS(UDCLASS_WIRELESS),
453 	  USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
454 	  USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
455 
456 	/* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
457 	{ USB_VPI(USB_VENDOR_AVM, 0x3800, 0) },
458 
459 	/* Broadcom USB dongles, mostly BCM20702 and BCM20702A0 */
460 	{ USB_VENDOR(USB_VENDOR_BROADCOM),
461 	  USB_IFACE_CLASS(UICLASS_VENDOR),
462 	  USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
463 	  USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
464 
465 	/* Apple-specific (Broadcom) devices */
466 	{ USB_VENDOR(USB_VENDOR_APPLE),
467 	  USB_IFACE_CLASS(UICLASS_VENDOR),
468 	  USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
469 	  USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
470 
471 	/* Foxconn - Hon Hai */
472 	{ USB_VENDOR(USB_VENDOR_FOXCONN),
473 	  USB_IFACE_CLASS(UICLASS_VENDOR),
474 	  USB_IFACE_SUBCLASS(UDSUBCLASS_RF),
475 	  USB_IFACE_PROTOCOL(UDPROTO_BLUETOOTH) },
476 
477 	/* MediaTek MT76x0E */
478 	{ USB_VPI(USB_VENDOR_MEDIATEK, 0x763f, 0) },
479 
480 	/* Broadcom SoftSailing reporting vendor specific */
481 	{ USB_VPI(USB_VENDOR_BROADCOM, 0x21e1, 0) },
482 
483 	/* Apple MacBookPro 7,1 */
484 	{ USB_VPI(USB_VENDOR_APPLE, 0x8213, 0) },
485 
486 	/* Apple iMac11,1 */
487 	{ USB_VPI(USB_VENDOR_APPLE, 0x8215, 0) },
488 
489 	/* Apple MacBookPro6,2 */
490 	{ USB_VPI(USB_VENDOR_APPLE, 0x8218, 0) },
491 
492 	/* Apple MacBookAir3,1, MacBookAir3,2 */
493 	{ USB_VPI(USB_VENDOR_APPLE, 0x821b, 0) },
494 
495 	/* Apple MacBookAir4,1 */
496 	{ USB_VPI(USB_VENDOR_APPLE, 0x821f, 0) },
497 
498 	/* MacBookAir6,1 */
499 	{ USB_VPI(USB_VENDOR_APPLE, 0x828f, 0) },
500 
501 	/* Apple MacBookPro8,2 */
502 	{ USB_VPI(USB_VENDOR_APPLE, 0x821a, 0) },
503 
504 	/* Apple MacMini5,1 */
505 	{ USB_VPI(USB_VENDOR_APPLE, 0x8281, 0) },
506 
507 	/* Bluetooth Ultraport Module from IBM */
508 	{ USB_VPI(USB_VENDOR_TDK, 0x030a, 0) },
509 
510 	/* ALPS Modules with non-standard ID */
511 	{ USB_VPI(USB_VENDOR_ALPS, 0x3001, 0) },
512 	{ USB_VPI(USB_VENDOR_ALPS, 0x3002, 0) },
513 
514 	{ USB_VPI(USB_VENDOR_ERICSSON2, 0x1002, 0) },
515 
516 	/* Canyon CN-BTU1 with HID interfaces */
517 	{ USB_VPI(USB_VENDOR_CANYON, 0x0000, 0) },
518 
519 	/* Broadcom BCM20702A0 */
520 	{ USB_VPI(USB_VENDOR_ASUS, 0x17b5, 0) },
521 	{ USB_VPI(USB_VENDOR_ASUS, 0x17cb, 0) },
522 	{ USB_VPI(USB_VENDOR_LITEON, 0x2003, 0) },
523 	{ USB_VPI(USB_VENDOR_FOXCONN, 0xe042, 0) },
524 	{ USB_VPI(USB_VENDOR_DELL, 0x8197, 0) },
525 	{ USB_VPI(USB_VENDOR_BELKIN, 0x065a, 0) },
526 };
527 
528 /*
529  * Does a synchronous (waits for completion event) execution of HCI command.
530  * Size of both command and response buffers are passed in length field of
531  * corresponding structures in "Parameter Total Length" format i.e.
532  * not including HCI packet headers.
533  * Expected event code must be placed into "Event code" of the response buffer.
534  *
535  * Must not be used after USB transfers have been configured in attach routine.
536  */
537 
538 usb_error_t
ubt_do_hci_request(struct usb_device * udev,struct ubt_hci_cmd * cmd,void * evt,usb_timeout_t timeout)539 ubt_do_hci_request(struct usb_device *udev, struct ubt_hci_cmd *cmd,
540     void *evt, usb_timeout_t timeout)
541 {
542 	static const struct usb_config ubt_probe_config = {
543 		.type = UE_INTERRUPT,
544 		.endpoint = UE_ADDR_ANY,
545 		.direction = UE_DIR_IN,
546 		.flags = { .pipe_bof = 1, .short_xfer_ok = 1 },
547 		.bufsize = UBT_INTR_BUFFER_SIZE,
548 		.callback = &ubt_probe_intr_callback,
549 	};
550 	struct usb_device_request req;
551 	struct usb_xfer *xfer[1];
552 	struct mtx mtx;
553 	usb_error_t error = USB_ERR_NORMAL_COMPLETION;
554 	uint8_t iface_index = 0;
555 
556 	/* Initialize a USB control request and then do it */
557 	bzero(&req, sizeof(req));
558 	req.bmRequestType = UBT_HCI_REQUEST;
559 	req.wIndex[0] = iface_index;
560 	USETW(req.wLength, UBT_HCI_CMD_SIZE(cmd));
561 
562 	error = usbd_do_request(udev, NULL, &req, cmd);
563 	if (error != USB_ERR_NORMAL_COMPLETION) {
564 		printf("ng_ubt: usbd_do_request error=%s\n",
565 			usbd_errstr(error));
566 		return (error);
567 	}
568 
569 	if (evt == NULL)
570 		return (USB_ERR_NORMAL_COMPLETION);
571 
572 	/* Save operation code if we expect completion event in response */
573 	if(((struct ubt_hci_event *)evt)->header.event ==
574 	    NG_HCI_EVENT_COMMAND_COMPL)
575 		((struct ubt_hci_event_command_compl *)evt)->opcode =
576 		  cmd->opcode;
577 
578 	/* Initialize INTR endpoint xfer and wait for response */
579 	mtx_init(&mtx, "ubt pb", NULL, MTX_DEF | MTX_NEW);
580 
581 	error = usbd_transfer_setup(udev, &iface_index, xfer,
582 	    &ubt_probe_config, 1, evt, &mtx);
583 	if (error == USB_ERR_NORMAL_COMPLETION) {
584 		mtx_lock(&mtx);
585 		usbd_transfer_start(*xfer);
586 
587 		if (msleep_sbt(evt, &mtx, 0, "ubt pb", SBT_1MS * timeout,
588 				0, C_HARDCLOCK) == EWOULDBLOCK) {
589 			printf("ng_ubt: HCI command 0x%04x timed out\n",
590 				le16toh(cmd->opcode));
591 			error = USB_ERR_TIMEOUT;
592 		}
593 
594 		usbd_transfer_stop(*xfer);
595 		mtx_unlock(&mtx);
596 
597 		usbd_transfer_unsetup(xfer, 1);
598 	} else
599 		printf("ng_ubt: usbd_transfer_setup error=%s\n",
600 			usbd_errstr(error));
601 
602 	mtx_destroy(&mtx);
603 
604 	return (error);
605 }
606 
607 /*
608  * Probe for a USB Bluetooth device.
609  * USB context.
610  */
611 
612 static int
ubt_probe(device_t dev)613 ubt_probe(device_t dev)
614 {
615 	struct usb_attach_arg	*uaa = device_get_ivars(dev);
616 	const struct usb_device_id *id;
617 
618 	if (uaa->usb_mode != USB_MODE_HOST)
619 		return (ENXIO);
620 
621 	if (usbd_lookup_id_by_uaa(ubt_ignore_devs,
622 			sizeof(ubt_ignore_devs), uaa) == 0)
623 		return (ENXIO);
624 	if (usbd_lookup_id_by_uaa(ubt_rtl_devs,
625 			ubt_rtl_devs_sizeof, uaa) == 0)
626 		return (ENXIO);
627 
628 	id = usbd_lookup_id_by_info(ubt_devs,
629 	    sizeof(ubt_devs), &uaa->info);
630 	if (id == NULL)
631 		return (ENXIO);
632 
633 	if (uaa->info.bIfaceIndex != 0) {
634 		/* make sure we are matching the interface */
635 		if (id->match_flag_int_class &&
636 		    id->match_flag_int_subclass &&
637 		    id->match_flag_int_protocol)
638 			return (BUS_PROBE_GENERIC);
639 		else
640 			return (ENXIO);
641 	} else {
642 		return (BUS_PROBE_GENERIC);
643 	}
644 } /* ubt_probe */
645 
646 /*
647  * Attach the device.
648  * USB context.
649  */
650 
651 static int
ubt_attach(device_t dev)652 ubt_attach(device_t dev)
653 {
654 	struct usb_attach_arg		*uaa = device_get_ivars(dev);
655 	struct ubt_softc		*sc = device_get_softc(dev);
656 	struct usb_endpoint_descriptor	*ed;
657 	struct usb_interface_descriptor *id;
658 	struct usb_interface		*iface[2];
659 	uint32_t			wMaxPacketSize;
660 	uint8_t				alt_index, i, j;
661 	uint8_t				iface_index[2];
662 
663 	device_set_usb_desc(dev);
664 
665 	iface_index[0] = uaa->info.bIfaceIndex;
666 	iface_index[1] = uaa->info.bIfaceIndex + 1;
667 
668 	iface[0] = usbd_get_iface(uaa->device, iface_index[0]);
669 	iface[1] = usbd_get_iface(uaa->device, iface_index[1]);
670 
671 	sc->sc_dev = dev;
672 	sc->sc_debug = NG_UBT_WARN_LEVEL;
673 
674 	/*
675 	 * Sanity checks.
676 	 */
677 
678 	if (iface[0] == NULL || iface[1] == NULL ||
679 	    iface[0]->idesc == NULL || iface[1]->idesc == NULL) {
680 		UBT_ALERT(sc, "could not get two interfaces\n");
681 		return (ENXIO);
682 	}
683 
684 	/*
685 	 * Create Netgraph node
686 	 */
687 
688 	if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
689 		UBT_ALERT(sc, "could not create Netgraph node\n");
690 		return (ENXIO);
691 	}
692 
693 	/* Name Netgraph node */
694 	if (ng_name_node(sc->sc_node, device_get_nameunit(dev)) != 0) {
695 		UBT_ALERT(sc, "could not name Netgraph node\n");
696 		NG_NODE_UNREF(sc->sc_node);
697 		return (ENXIO);
698 	}
699 	NG_NODE_SET_PRIVATE(sc->sc_node, sc);
700 	NG_NODE_FORCE_WRITER(sc->sc_node);
701 
702 	/*
703 	 * Initialize device softc structure
704 	 */
705 
706 	/* initialize locks */
707 	mtx_init(&sc->sc_ng_mtx, "ubt ng", NULL, MTX_DEF);
708 	mtx_init(&sc->sc_if_mtx, "ubt if", NULL, MTX_DEF | MTX_RECURSE);
709 
710 	/* initialize packet queues */
711 	NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
712 	NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
713 	NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
714 
715 	/* initialize glue task */
716 	TASK_INIT(&sc->sc_task, 0, ubt_task, sc);
717 
718 	/*
719 	 * Configure Bluetooth USB device. Discover all required USB
720 	 * interfaces and endpoints.
721 	 *
722 	 * USB device must present two interfaces:
723 	 * 1) Interface 0 that has 3 endpoints
724 	 *	1) Interrupt endpoint to receive HCI events
725 	 *	2) Bulk IN endpoint to receive ACL data
726 	 *	3) Bulk OUT endpoint to send ACL data
727 	 *
728 	 * 2) Interface 1 then has 2 endpoints
729 	 *	1) Isochronous IN endpoint to receive SCO data
730  	 *	2) Isochronous OUT endpoint to send SCO data
731 	 *
732 	 * Interface 1 (with isochronous endpoints) has several alternate
733 	 * configurations with different packet size.
734 	 */
735 
736 	/*
737 	 * For interface #1 search alternate settings, and find
738 	 * the descriptor with the largest wMaxPacketSize
739 	 */
740 
741 	wMaxPacketSize = 0;
742 	alt_index = 0;
743 	i = 0;
744 	j = 0;
745 	ed = NULL;
746 
747 	/*
748 	 * Search through all the descriptors looking for the largest
749 	 * packet size:
750 	 */
751 	while ((ed = (struct usb_endpoint_descriptor *)usb_desc_foreach(
752 	    usbd_get_config_descriptor(uaa->device),
753 	    (struct usb_descriptor *)ed))) {
754 		if ((ed->bDescriptorType == UDESC_INTERFACE) &&
755 		    (ed->bLength >= sizeof(*id))) {
756 			id = (struct usb_interface_descriptor *)ed;
757 			i = (id->bInterfaceNumber == iface[1]->idesc->bInterfaceNumber);
758 			j = id->bAlternateSetting;
759 		}
760 
761 		if ((ed->bDescriptorType == UDESC_ENDPOINT) &&
762 		    (ed->bLength >= sizeof(*ed)) &&
763 		    (i != 0)) {
764 			uint32_t temp;
765 
766 			temp = usbd_get_max_frame_length(
767 			    ed, NULL, usbd_get_speed(uaa->device));
768 			if (temp > wMaxPacketSize) {
769 				wMaxPacketSize = temp;
770 				alt_index = j;
771 			}
772 		}
773 	}
774 
775 	/* Set alt configuration on interface #1 only if we found it */
776 	if (wMaxPacketSize > 0 &&
777 	    usbd_set_alt_interface_index(uaa->device, iface_index[1], alt_index)) {
778 		UBT_ALERT(sc, "could not set alternate setting %d " \
779 			"for interface 1!\n", alt_index);
780 		goto detach;
781 	}
782 
783 	/* Setup transfers for both interfaces */
784 	if (usbd_transfer_setup(uaa->device, iface_index, sc->sc_xfer, ubt_config,
785 			ng_usb_isoc_enable ? UBT_N_TRANSFER : UBT_IF_1_ISOC_DT_RD1,
786 			sc, &sc->sc_if_mtx)) {
787 		UBT_ALERT(sc, "could not allocate transfers\n");
788 		goto detach;
789 	}
790 
791 	/* Claim second interface belonging to the Bluetooth part */
792 	usbd_set_parent_iface(uaa->device, iface_index[1], uaa->info.bIfaceIndex);
793 
794 	return (0); /* success */
795 
796 detach:
797 	ubt_detach(dev);
798 
799 	return (ENXIO);
800 } /* ubt_attach */
801 
802 /*
803  * Detach the device.
804  * USB context.
805  */
806 
807 int
ubt_detach(device_t dev)808 ubt_detach(device_t dev)
809 {
810 	struct ubt_softc	*sc = device_get_softc(dev);
811 	node_p			node = sc->sc_node;
812 
813 	/* Destroy Netgraph node */
814 	if (node != NULL) {
815 		sc->sc_node = NULL;
816 		NG_NODE_REALLY_DIE(node);
817 		ng_rmnode_self(node);
818 	}
819 
820 	/* Make sure ubt_task in gone */
821 	taskqueue_drain(taskqueue_swi, &sc->sc_task);
822 
823 	/* Free USB transfers, if any */
824 	usbd_transfer_unsetup(sc->sc_xfer, UBT_N_TRANSFER);
825 
826 	/* Destroy queues */
827 	UBT_NG_LOCK(sc);
828 	NG_BT_MBUFQ_DESTROY(&sc->sc_cmdq);
829 	NG_BT_MBUFQ_DESTROY(&sc->sc_aclq);
830 	NG_BT_MBUFQ_DESTROY(&sc->sc_scoq);
831 	UBT_NG_UNLOCK(sc);
832 
833 	mtx_destroy(&sc->sc_if_mtx);
834 	mtx_destroy(&sc->sc_ng_mtx);
835 
836 	return (0);
837 } /* ubt_detach */
838 
839 /*
840  * Called when incoming interrupt transfer (HCI event) has completed, i.e.
841  * HCI event was received from the device during device probe stage.
842  * USB context.
843  */
844 
845 static void
ubt_probe_intr_callback(struct usb_xfer * xfer,usb_error_t error)846 ubt_probe_intr_callback(struct usb_xfer *xfer, usb_error_t error)
847 {
848 	struct ubt_hci_event	*evt = usbd_xfer_softc(xfer);
849 	struct usb_page_cache	*pc;
850 	int			actlen;
851 	struct ubt_hci_evhdr	evhdr;
852 	uint16_t		opcode;
853 
854 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
855 
856 	switch (USB_GET_STATE(xfer)) {
857 	case USB_ST_TRANSFERRED:
858 		if (actlen > UBT_HCI_EVENT_SIZE(evt))
859 			actlen = UBT_HCI_EVENT_SIZE(evt);
860 		if (actlen < sizeof(evhdr))
861 			goto submit_next;
862 		pc = usbd_xfer_get_frame(xfer, 0);
863 		usbd_copy_out(pc, 0, &evhdr, sizeof(evhdr));
864 		/* Check for expected event code */
865 		if (evt->header.event != 0 &&
866 		    (evt->header.event != evhdr.event))
867 			goto submit_next;
868 		/* For completion events check operation code as well */
869 		if (evt->header.event == NG_HCI_EVENT_COMMAND_COMPL) {
870 			if (actlen < sizeof(struct ubt_hci_event_command_compl))
871 				goto submit_next;
872 			usbd_copy_out(pc,
873 			    offsetof(struct ubt_hci_event_command_compl, opcode),
874 			    &opcode, sizeof(opcode));
875 			if (opcode !=
876 			    ((struct ubt_hci_event_command_compl *)evt)->opcode)
877 				goto submit_next;
878 		}
879 		usbd_copy_out(pc, 0, evt, actlen);
880 		/* OneShot mode */
881 		wakeup(evt);
882 		break;
883 
884         case USB_ST_SETUP:
885 submit_next:
886 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
887 		usbd_transfer_submit(xfer);
888 		break;
889 
890 	default:
891 		if (error != USB_ERR_CANCELLED) {
892 			printf("ng_ubt: interrupt transfer failed: %s\n",
893 				usbd_errstr(error));
894 			/* Try clear stall first */
895 			usbd_xfer_set_stall(xfer);
896 			goto submit_next;
897 		}
898 		break;
899 	}
900 } /* ubt_probe_intr_callback */
901 
902 /*
903  * Called when outgoing control request (HCI command) has completed, i.e.
904  * HCI command was sent to the device.
905  * USB context.
906  */
907 
908 static void
ubt_ctrl_write_callback(struct usb_xfer * xfer,usb_error_t error)909 ubt_ctrl_write_callback(struct usb_xfer *xfer, usb_error_t error)
910 {
911 	struct ubt_softc		*sc = usbd_xfer_softc(xfer);
912 	struct usb_device_request	req;
913 	struct mbuf			*m;
914 	struct usb_page_cache		*pc;
915 	int				actlen;
916 
917 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
918 
919 	switch (USB_GET_STATE(xfer)) {
920 	case USB_ST_TRANSFERRED:
921 		UBT_INFO(sc, "sent %d bytes to control pipe\n", actlen);
922 		UBT_STAT_BYTES_SENT(sc, actlen);
923 		UBT_STAT_PCKTS_SENT(sc);
924 		/* FALLTHROUGH */
925 
926 	case USB_ST_SETUP:
927 send_next:
928 		/* Get next command mbuf, if any */
929 		UBT_NG_LOCK(sc);
930 		NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
931 		UBT_NG_UNLOCK(sc);
932 
933 		if (m == NULL) {
934 			UBT_INFO(sc, "HCI command queue is empty\n");
935 			break;	/* transfer complete */
936 		}
937 
938 		/* Initialize a USB control request and then schedule it */
939 		bzero(&req, sizeof(req));
940 		req.bmRequestType = UBT_HCI_REQUEST;
941 		USETW(req.wLength, m->m_pkthdr.len);
942 
943 		UBT_INFO(sc, "Sending control request, " \
944 			"bmRequestType=0x%02x, wLength=%d\n",
945 			req.bmRequestType, UGETW(req.wLength));
946 
947 		pc = usbd_xfer_get_frame(xfer, 0);
948 		usbd_copy_in(pc, 0, &req, sizeof(req));
949 		pc = usbd_xfer_get_frame(xfer, 1);
950 		usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len);
951 
952 		usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
953 		usbd_xfer_set_frame_len(xfer, 1, m->m_pkthdr.len);
954 		usbd_xfer_set_frames(xfer, 2);
955 
956 		NG_FREE_M(m);
957 
958 		usbd_transfer_submit(xfer);
959 		break;
960 
961 	default: /* Error */
962 		if (error != USB_ERR_CANCELLED) {
963 			UBT_WARN(sc, "control transfer failed: %s\n",
964 				usbd_errstr(error));
965 
966 			UBT_STAT_OERROR(sc);
967 			goto send_next;
968 		}
969 
970 		/* transfer cancelled */
971 		break;
972 	}
973 } /* ubt_ctrl_write_callback */
974 
975 /*
976  * Called when incoming interrupt transfer (HCI event) has completed, i.e.
977  * HCI event was received from the device.
978  * USB context.
979  */
980 
981 static void
ubt_intr_read_callback(struct usb_xfer * xfer,usb_error_t error)982 ubt_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
983 {
984 	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
985 	struct mbuf		*m;
986 	ng_hci_event_pkt_t	*hdr;
987 	struct usb_page_cache	*pc;
988 	int			actlen;
989 
990 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
991 
992 	m = NULL;
993 
994 	switch (USB_GET_STATE(xfer)) {
995 	case USB_ST_TRANSFERRED:
996 		/* Allocate a new mbuf */
997 		MGETHDR(m, M_NOWAIT, MT_DATA);
998 		if (m == NULL) {
999 			UBT_STAT_IERROR(sc);
1000 			goto submit_next;
1001 		}
1002 
1003 		if (!(MCLGET(m, M_NOWAIT))) {
1004 			UBT_STAT_IERROR(sc);
1005 			goto submit_next;
1006 		}
1007 
1008 		/* Add HCI packet type */
1009 		*mtod(m, uint8_t *)= NG_HCI_EVENT_PKT;
1010 		m->m_pkthdr.len = m->m_len = 1;
1011 
1012 		if (actlen > MCLBYTES - 1)
1013 			actlen = MCLBYTES - 1;
1014 
1015 		pc = usbd_xfer_get_frame(xfer, 0);
1016 		usbd_copy_out(pc, 0, mtod(m, uint8_t *) + 1, actlen);
1017 		m->m_pkthdr.len += actlen;
1018 		m->m_len += actlen;
1019 
1020 		UBT_INFO(sc, "got %d bytes from interrupt pipe\n",
1021 			actlen);
1022 
1023 		/* Validate packet and send it up the stack */
1024 		if (m->m_pkthdr.len < (int)sizeof(*hdr)) {
1025 			UBT_INFO(sc, "HCI event packet is too short\n");
1026 
1027 			UBT_STAT_IERROR(sc);
1028 			goto submit_next;
1029 		}
1030 
1031 		hdr = mtod(m, ng_hci_event_pkt_t *);
1032 		if (hdr->length != (m->m_pkthdr.len - sizeof(*hdr))) {
1033 			UBT_ERR(sc, "Invalid HCI event packet size, " \
1034 				"length=%d, pktlen=%d\n",
1035 				hdr->length, m->m_pkthdr.len);
1036 
1037 			UBT_STAT_IERROR(sc);
1038 			goto submit_next;
1039 		}
1040 
1041 		UBT_INFO(sc, "got complete HCI event frame, pktlen=%d, " \
1042 			"length=%d\n", m->m_pkthdr.len, hdr->length);
1043 
1044 		UBT_STAT_PCKTS_RECV(sc);
1045 		UBT_STAT_BYTES_RECV(sc, m->m_pkthdr.len);
1046 
1047 		ubt_fwd_mbuf_up(sc, &m);
1048 		/* m == NULL at this point */
1049 		/* FALLTHROUGH */
1050 
1051 	case USB_ST_SETUP:
1052 submit_next:
1053 		NG_FREE_M(m); /* checks for m != NULL */
1054 
1055 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1056 		usbd_transfer_submit(xfer);
1057 		break;
1058 
1059 	default: /* Error */
1060 		if (error != USB_ERR_CANCELLED) {
1061 			UBT_WARN(sc, "interrupt transfer failed: %s\n",
1062 				usbd_errstr(error));
1063 
1064 			/* Try to clear stall first */
1065 			usbd_xfer_set_stall(xfer);
1066 			goto submit_next;
1067 		}
1068 			/* transfer cancelled */
1069 		break;
1070 	}
1071 } /* ubt_intr_read_callback */
1072 
1073 /*
1074  * Called when incoming bulk transfer (ACL packet) has completed, i.e.
1075  * ACL packet was received from the device.
1076  * USB context.
1077  */
1078 
1079 static void
ubt_bulk_read_callback(struct usb_xfer * xfer,usb_error_t error)1080 ubt_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
1081 {
1082 	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
1083 	struct mbuf		*m;
1084 	ng_hci_acldata_pkt_t	*hdr;
1085 	struct usb_page_cache	*pc;
1086 	int len;
1087 	int actlen;
1088 
1089 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1090 
1091 	m = NULL;
1092 
1093 	switch (USB_GET_STATE(xfer)) {
1094 	case USB_ST_TRANSFERRED:
1095 		/* Allocate new mbuf */
1096 		MGETHDR(m, M_NOWAIT, MT_DATA);
1097 		if (m == NULL) {
1098 			UBT_STAT_IERROR(sc);
1099 			goto submit_next;
1100 		}
1101 
1102 		if (!(MCLGET(m, M_NOWAIT))) {
1103 			UBT_STAT_IERROR(sc);
1104 			goto submit_next;
1105 		}
1106 
1107 		/* Add HCI packet type */
1108 		*mtod(m, uint8_t *)= NG_HCI_ACL_DATA_PKT;
1109 		m->m_pkthdr.len = m->m_len = 1;
1110 
1111 		if (actlen > MCLBYTES - 1)
1112 			actlen = MCLBYTES - 1;
1113 
1114 		pc = usbd_xfer_get_frame(xfer, 0);
1115 		usbd_copy_out(pc, 0, mtod(m, uint8_t *) + 1, actlen);
1116 		m->m_pkthdr.len += actlen;
1117 		m->m_len += actlen;
1118 
1119 		UBT_INFO(sc, "got %d bytes from bulk-in pipe\n",
1120 			actlen);
1121 
1122 		/* Validate packet and send it up the stack */
1123 		if (m->m_pkthdr.len < (int)sizeof(*hdr)) {
1124 			UBT_INFO(sc, "HCI ACL packet is too short\n");
1125 
1126 			UBT_STAT_IERROR(sc);
1127 			goto submit_next;
1128 		}
1129 
1130 		hdr = mtod(m, ng_hci_acldata_pkt_t *);
1131 		len = le16toh(hdr->length);
1132 		if (len != (int)(m->m_pkthdr.len - sizeof(*hdr))) {
1133 			UBT_ERR(sc, "Invalid ACL packet size, length=%d, " \
1134 				"pktlen=%d\n", len, m->m_pkthdr.len);
1135 
1136 			UBT_STAT_IERROR(sc);
1137 			goto submit_next;
1138 		}
1139 
1140 		UBT_INFO(sc, "got complete ACL data packet, pktlen=%d, " \
1141 			"length=%d\n", m->m_pkthdr.len, len);
1142 
1143 		UBT_STAT_PCKTS_RECV(sc);
1144 		UBT_STAT_BYTES_RECV(sc, m->m_pkthdr.len);
1145 
1146 		ubt_fwd_mbuf_up(sc, &m);
1147 		/* m == NULL at this point */
1148 		/* FALLTHOUGH */
1149 
1150 	case USB_ST_SETUP:
1151 submit_next:
1152 		NG_FREE_M(m); /* checks for m != NULL */
1153 
1154 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1155 		usbd_transfer_submit(xfer);
1156 		break;
1157 
1158 	default: /* Error */
1159 		if (error != USB_ERR_CANCELLED) {
1160 			UBT_WARN(sc, "bulk-in transfer failed: %s\n",
1161 				usbd_errstr(error));
1162 
1163 			/* Try to clear stall first */
1164 			usbd_xfer_set_stall(xfer);
1165 			goto submit_next;
1166 		}
1167 			/* transfer cancelled */
1168 		break;
1169 	}
1170 } /* ubt_bulk_read_callback */
1171 
1172 /*
1173  * Called when outgoing bulk transfer (ACL packet) has completed, i.e.
1174  * ACL packet was sent to the device.
1175  * USB context.
1176  */
1177 
1178 static void
ubt_bulk_write_callback(struct usb_xfer * xfer,usb_error_t error)1179 ubt_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
1180 {
1181 	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
1182 	struct mbuf		*m;
1183 	struct usb_page_cache	*pc;
1184 	int			actlen;
1185 
1186 	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1187 
1188 	switch (USB_GET_STATE(xfer)) {
1189 	case USB_ST_TRANSFERRED:
1190 		UBT_INFO(sc, "sent %d bytes to bulk-out pipe\n", actlen);
1191 		UBT_STAT_BYTES_SENT(sc, actlen);
1192 		UBT_STAT_PCKTS_SENT(sc);
1193 		/* FALLTHROUGH */
1194 
1195 	case USB_ST_SETUP:
1196 send_next:
1197 		/* Get next mbuf, if any */
1198 		UBT_NG_LOCK(sc);
1199 		NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1200 		UBT_NG_UNLOCK(sc);
1201 
1202 		if (m == NULL) {
1203 			UBT_INFO(sc, "ACL data queue is empty\n");
1204 			break; /* transfer completed */
1205 		}
1206 
1207 		/*
1208 		 * Copy ACL data frame back to a linear USB transfer buffer
1209 		 * and schedule transfer
1210 		 */
1211 
1212 		pc = usbd_xfer_get_frame(xfer, 0);
1213 		usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len);
1214 		usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len);
1215 
1216 		UBT_INFO(sc, "bulk-out transfer has been started, len=%d\n",
1217 			m->m_pkthdr.len);
1218 
1219 		NG_FREE_M(m);
1220 
1221 		usbd_transfer_submit(xfer);
1222 		break;
1223 
1224 	default: /* Error */
1225 		if (error != USB_ERR_CANCELLED) {
1226 			UBT_WARN(sc, "bulk-out transfer failed: %s\n",
1227 				usbd_errstr(error));
1228 
1229 			UBT_STAT_OERROR(sc);
1230 
1231 			/* try to clear stall first */
1232 			usbd_xfer_set_stall(xfer);
1233 			goto send_next;
1234 		}
1235 			/* transfer cancelled */
1236 		break;
1237 	}
1238 } /* ubt_bulk_write_callback */
1239 
1240 /*
1241  * Called when incoming isoc transfer (SCO packet) has completed, i.e.
1242  * SCO packet was received from the device.
1243  * USB context.
1244  */
1245 
1246 static void
ubt_isoc_read_callback(struct usb_xfer * xfer,usb_error_t error)1247 ubt_isoc_read_callback(struct usb_xfer *xfer, usb_error_t error)
1248 {
1249 	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
1250 	int			n;
1251 	int actlen, nframes;
1252 
1253 	usbd_xfer_status(xfer, &actlen, NULL, NULL, &nframes);
1254 
1255 	switch (USB_GET_STATE(xfer)) {
1256 	case USB_ST_TRANSFERRED:
1257 		for (n = 0; n < nframes; n ++)
1258 			if (ubt_isoc_read_one_frame(xfer, n) < 0)
1259 				break;
1260 		/* FALLTHROUGH */
1261 
1262 	case USB_ST_SETUP:
1263 read_next:
1264 		for (n = 0; n < nframes; n ++)
1265 			usbd_xfer_set_frame_len(xfer, n,
1266 			    usbd_xfer_max_framelen(xfer));
1267 
1268 		usbd_transfer_submit(xfer);
1269 		break;
1270 
1271 	default: /* Error */
1272                 if (error != USB_ERR_CANCELLED) {
1273                         UBT_STAT_IERROR(sc);
1274                         goto read_next;
1275                 }
1276 
1277 		/* transfer cancelled */
1278 		break;
1279 	}
1280 } /* ubt_isoc_read_callback */
1281 
1282 /*
1283  * Helper function. Called from ubt_isoc_read_callback() to read
1284  * SCO data from one frame.
1285  * USB context.
1286  */
1287 
1288 static int
ubt_isoc_read_one_frame(struct usb_xfer * xfer,int frame_no)1289 ubt_isoc_read_one_frame(struct usb_xfer *xfer, int frame_no)
1290 {
1291 	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
1292 	struct usb_page_cache	*pc;
1293 	struct mbuf		*m;
1294 	int			len, want, got, total;
1295 
1296 	/* Get existing SCO reassembly buffer */
1297 	pc = usbd_xfer_get_frame(xfer, 0);
1298 	m = sc->sc_isoc_in_buffer;
1299 	total = usbd_xfer_frame_len(xfer, frame_no);
1300 
1301 	/* While we have data in the frame */
1302 	while (total > 0) {
1303 		if (m == NULL) {
1304 			/* Start new reassembly buffer */
1305 			MGETHDR(m, M_NOWAIT, MT_DATA);
1306 			if (m == NULL) {
1307 				UBT_STAT_IERROR(sc);
1308 				return (-1);	/* XXX out of sync! */
1309 			}
1310 
1311 			if (!(MCLGET(m, M_NOWAIT))) {
1312 				UBT_STAT_IERROR(sc);
1313 				NG_FREE_M(m);
1314 				return (-1);	/* XXX out of sync! */
1315 			}
1316 
1317 			/* Expect SCO header */
1318 			*mtod(m, uint8_t *) = NG_HCI_SCO_DATA_PKT;
1319 			m->m_pkthdr.len = m->m_len = got = 1;
1320 			want = sizeof(ng_hci_scodata_pkt_t);
1321 		} else {
1322 			/*
1323 			 * Check if we have SCO header and if so
1324 			 * adjust amount of data we want
1325 			 */
1326 			got = m->m_pkthdr.len;
1327 			want = sizeof(ng_hci_scodata_pkt_t);
1328 
1329 			if (got >= want)
1330 				want += mtod(m, ng_hci_scodata_pkt_t *)->length;
1331 		}
1332 
1333 		/* Append frame data to the SCO reassembly buffer */
1334 		len = total;
1335 		if (got + len > want)
1336 			len = want - got;
1337 
1338 		usbd_copy_out(pc, frame_no * usbd_xfer_max_framelen(xfer),
1339 			mtod(m, uint8_t *) + m->m_pkthdr.len, len);
1340 
1341 		m->m_pkthdr.len += len;
1342 		m->m_len += len;
1343 		total -= len;
1344 
1345 		/* Check if we got everything we wanted, if not - continue */
1346 		if (got != want)
1347 			continue;
1348 
1349 		/* If we got here then we got complete SCO frame */
1350 		UBT_INFO(sc, "got complete SCO data frame, pktlen=%d, " \
1351 			"length=%d\n", m->m_pkthdr.len,
1352 			mtod(m, ng_hci_scodata_pkt_t *)->length);
1353 
1354 		UBT_STAT_PCKTS_RECV(sc);
1355 		UBT_STAT_BYTES_RECV(sc, m->m_pkthdr.len);
1356 
1357 		ubt_fwd_mbuf_up(sc, &m);
1358 		/* m == NULL at this point */
1359 	}
1360 
1361 	/* Put SCO reassembly buffer back */
1362 	sc->sc_isoc_in_buffer = m;
1363 
1364 	return (0);
1365 } /* ubt_isoc_read_one_frame */
1366 
1367 /*
1368  * Called when outgoing isoc transfer (SCO packet) has completed, i.e.
1369  * SCO packet was sent to the device.
1370  * USB context.
1371  */
1372 
1373 static void
ubt_isoc_write_callback(struct usb_xfer * xfer,usb_error_t error)1374 ubt_isoc_write_callback(struct usb_xfer *xfer, usb_error_t error)
1375 {
1376 	struct ubt_softc	*sc = usbd_xfer_softc(xfer);
1377 	struct usb_page_cache	*pc;
1378 	struct mbuf		*m;
1379 	int			n, space, offset;
1380 	int			actlen, nframes;
1381 
1382 	usbd_xfer_status(xfer, &actlen, NULL, NULL, &nframes);
1383 	pc = usbd_xfer_get_frame(xfer, 0);
1384 
1385 	switch (USB_GET_STATE(xfer)) {
1386 	case USB_ST_TRANSFERRED:
1387 		UBT_INFO(sc, "sent %d bytes to isoc-out pipe\n", actlen);
1388 		UBT_STAT_BYTES_SENT(sc, actlen);
1389 		UBT_STAT_PCKTS_SENT(sc);
1390 		/* FALLTHROUGH */
1391 
1392 	case USB_ST_SETUP:
1393 send_next:
1394 		offset = 0;
1395 		space = usbd_xfer_max_framelen(xfer) * nframes;
1396 		m = NULL;
1397 
1398 		while (space > 0) {
1399 			if (m == NULL) {
1400 				UBT_NG_LOCK(sc);
1401 				NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1402 				UBT_NG_UNLOCK(sc);
1403 
1404 				if (m == NULL)
1405 					break;
1406 			}
1407 
1408 			n = min(space, m->m_pkthdr.len);
1409 			if (n > 0) {
1410 				usbd_m_copy_in(pc, offset, m,0, n);
1411 				m_adj(m, n);
1412 
1413 				offset += n;
1414 				space -= n;
1415 			}
1416 
1417 			if (m->m_pkthdr.len == 0)
1418 				NG_FREE_M(m); /* sets m = NULL */
1419 		}
1420 
1421 		/* Put whatever is left from mbuf back on queue */
1422 		if (m != NULL) {
1423 			UBT_NG_LOCK(sc);
1424 			NG_BT_MBUFQ_PREPEND(&sc->sc_scoq, m);
1425 			UBT_NG_UNLOCK(sc);
1426 		}
1427 
1428 		/*
1429 		 * Calculate sizes for isoc frames.
1430 		 * Note that offset could be 0 at this point (i.e. we have
1431 		 * nothing to send). That is fine, as we have isoc. transfers
1432 		 * going in both directions all the time. In this case it
1433 		 * would be just empty isoc. transfer.
1434 		 */
1435 
1436 		for (n = 0; n < nframes; n ++) {
1437 			usbd_xfer_set_frame_len(xfer, n,
1438 			    min(offset, usbd_xfer_max_framelen(xfer)));
1439 			offset -= usbd_xfer_frame_len(xfer, n);
1440 		}
1441 
1442 		usbd_transfer_submit(xfer);
1443 		break;
1444 
1445 	default: /* Error */
1446 		if (error != USB_ERR_CANCELLED) {
1447 			UBT_STAT_OERROR(sc);
1448 			goto send_next;
1449 		}
1450 
1451 		/* transfer cancelled */
1452 		break;
1453 	}
1454 }
1455 
1456 /*
1457  * Utility function to forward provided mbuf upstream (i.e. up the stack).
1458  * Modifies value of the mbuf pointer (sets it to NULL).
1459  * Save to call from any context.
1460  */
1461 
1462 static int
ubt_fwd_mbuf_up(ubt_softc_p sc,struct mbuf ** m)1463 ubt_fwd_mbuf_up(ubt_softc_p sc, struct mbuf **m)
1464 {
1465 	hook_p	hook;
1466 	int	error;
1467 
1468 	/*
1469 	 * Close the race with Netgraph hook newhook/disconnect methods.
1470 	 * Save the hook pointer atomically. Two cases are possible:
1471 	 *
1472 	 * 1) The hook pointer is NULL. It means disconnect method got
1473 	 *    there first. In this case we are done.
1474 	 *
1475 	 * 2) The hook pointer is not NULL. It means that hook pointer
1476 	 *    could be either in valid or invalid (i.e. in the process
1477 	 *    of disconnect) state. In any case grab an extra reference
1478 	 *    to protect the hook pointer.
1479 	 *
1480 	 * It is ok to pass hook in invalid state to NG_SEND_DATA_ONLY() as
1481 	 * it checks for it. Drop extra reference after NG_SEND_DATA_ONLY().
1482 	 */
1483 
1484 	UBT_NG_LOCK(sc);
1485 	if ((hook = sc->sc_hook) != NULL)
1486 		NG_HOOK_REF(hook);
1487 	UBT_NG_UNLOCK(sc);
1488 
1489 	if (hook == NULL) {
1490 		NG_FREE_M(*m);
1491 		return (ENETDOWN);
1492 	}
1493 
1494 	NG_SEND_DATA_ONLY(error, hook, *m);
1495 	NG_HOOK_UNREF(hook);
1496 
1497 	if (error != 0)
1498 		UBT_STAT_IERROR(sc);
1499 
1500 	return (error);
1501 } /* ubt_fwd_mbuf_up */
1502 
1503 /****************************************************************************
1504  ****************************************************************************
1505  **                                 Glue
1506  ****************************************************************************
1507  ****************************************************************************/
1508 
1509 /*
1510  * Schedule glue task. Should be called with sc_ng_mtx held.
1511  * Netgraph context.
1512  */
1513 
1514 static void
ubt_task_schedule(ubt_softc_p sc,int action)1515 ubt_task_schedule(ubt_softc_p sc, int action)
1516 {
1517 	mtx_assert(&sc->sc_ng_mtx, MA_OWNED);
1518 
1519 	/*
1520 	 * Try to handle corner case when "start all" and "stop all"
1521 	 * actions can both be set before task is executed.
1522 	 *
1523 	 * The rules are
1524 	 *
1525 	 * sc_task_flags	action		new sc_task_flags
1526 	 * ------------------------------------------------------
1527 	 * 0			start		start
1528 	 * 0			stop		stop
1529 	 * start		start		start
1530 	 * start		stop		stop
1531 	 * stop			start		stop|start
1532 	 * stop			stop		stop
1533 	 * stop|start		start		stop|start
1534 	 * stop|start		stop		stop
1535 	 */
1536 
1537 	if (action != 0) {
1538 		if ((action & UBT_FLAG_T_STOP_ALL) != 0)
1539 			sc->sc_task_flags &= ~UBT_FLAG_T_START_ALL;
1540 
1541 		sc->sc_task_flags |= action;
1542 	}
1543 
1544 	if (sc->sc_task_flags & UBT_FLAG_T_PENDING)
1545 		return;
1546 
1547 	if (taskqueue_enqueue(taskqueue_swi, &sc->sc_task) == 0) {
1548 		sc->sc_task_flags |= UBT_FLAG_T_PENDING;
1549 		return;
1550 	}
1551 
1552 	/* XXX: i think this should never happen */
1553 } /* ubt_task_schedule */
1554 
1555 /*
1556  * Glue task. Examines sc_task_flags and does things depending on it.
1557  * Taskqueue context.
1558  */
1559 
1560 static void
ubt_task(void * context,int pending)1561 ubt_task(void *context, int pending)
1562 {
1563 	ubt_softc_p	sc = context;
1564 	int		task_flags, i;
1565 
1566 	UBT_NG_LOCK(sc);
1567 	task_flags = sc->sc_task_flags;
1568 	sc->sc_task_flags = 0;
1569 	UBT_NG_UNLOCK(sc);
1570 
1571 	/*
1572 	 * Stop all USB transfers synchronously.
1573 	 * Stop interface #0 and #1 transfers at the same time and in the
1574 	 * same loop. usbd_transfer_drain() will do appropriate locking.
1575 	 */
1576 
1577 	if (task_flags & UBT_FLAG_T_STOP_ALL)
1578 		for (i = 0; i < UBT_N_TRANSFER; i ++)
1579 			usbd_transfer_drain(sc->sc_xfer[i]);
1580 
1581 	/* Start incoming interrupt and bulk, and all isoc. USB transfers */
1582 	if (task_flags & UBT_FLAG_T_START_ALL) {
1583 		/*
1584 		 * Interface #0
1585 		 */
1586 
1587 		mtx_lock(&sc->sc_if_mtx);
1588 
1589 		ubt_xfer_start(sc, UBT_IF_0_INTR_DT_RD);
1590 		ubt_xfer_start(sc, UBT_IF_0_BULK_DT_RD);
1591 
1592 		/*
1593 		 * Interface #1
1594 		 * Start both read and write isoc. transfers by default.
1595 		 * Get them going all the time even if we have nothing
1596 		 * to send to avoid any delays.
1597 		 */
1598 
1599 		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_RD1);
1600 		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_RD2);
1601 		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_WR1);
1602 		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_WR2);
1603 
1604 		mtx_unlock(&sc->sc_if_mtx);
1605 	}
1606 
1607  	/* Start outgoing control transfer */
1608 	if (task_flags & UBT_FLAG_T_START_CTRL) {
1609 		mtx_lock(&sc->sc_if_mtx);
1610 		ubt_xfer_start(sc, UBT_IF_0_CTRL_DT_WR);
1611 		mtx_unlock(&sc->sc_if_mtx);
1612 	}
1613 
1614 	/* Start outgoing bulk transfer */
1615 	if (task_flags & UBT_FLAG_T_START_BULK) {
1616 		mtx_lock(&sc->sc_if_mtx);
1617 		ubt_xfer_start(sc, UBT_IF_0_BULK_DT_WR);
1618 		mtx_unlock(&sc->sc_if_mtx);
1619 	}
1620 } /* ubt_task */
1621 
1622 /****************************************************************************
1623  ****************************************************************************
1624  **                        Netgraph specific
1625  ****************************************************************************
1626  ****************************************************************************/
1627 
1628 /*
1629  * Netgraph node constructor. Do not allow to create node of this type.
1630  * Netgraph context.
1631  */
1632 
1633 static int
ng_ubt_constructor(node_p node)1634 ng_ubt_constructor(node_p node)
1635 {
1636 	return (EINVAL);
1637 } /* ng_ubt_constructor */
1638 
1639 /*
1640  * Netgraph node destructor. Destroy node only when device has been detached.
1641  * Netgraph context.
1642  */
1643 
1644 static int
ng_ubt_shutdown(node_p node)1645 ng_ubt_shutdown(node_p node)
1646 {
1647 	if (node->nd_flags & NGF_REALLY_DIE) {
1648 		/*
1649                  * We came here because the USB device is being
1650 		 * detached, so stop being persistent.
1651                  */
1652 		NG_NODE_SET_PRIVATE(node, NULL);
1653 		NG_NODE_UNREF(node);
1654 	} else
1655 		NG_NODE_REVIVE(node); /* tell ng_rmnode we are persisant */
1656 
1657 	return (0);
1658 } /* ng_ubt_shutdown */
1659 
1660 /*
1661  * Create new hook. There can only be one.
1662  * Netgraph context.
1663  */
1664 
1665 static int
ng_ubt_newhook(node_p node,hook_p hook,char const * name)1666 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1667 {
1668 	struct ubt_softc	*sc = NG_NODE_PRIVATE(node);
1669 
1670 	if (strcmp(name, NG_UBT_HOOK) != 0)
1671 		return (EINVAL);
1672 
1673 	UBT_NG_LOCK(sc);
1674 	if (sc->sc_hook != NULL) {
1675 		UBT_NG_UNLOCK(sc);
1676 
1677 		return (EISCONN);
1678 	}
1679 
1680 	sc->sc_hook = hook;
1681 	UBT_NG_UNLOCK(sc);
1682 
1683 	return (0);
1684 } /* ng_ubt_newhook */
1685 
1686 /*
1687  * Connect hook. Start incoming USB transfers.
1688  * Netgraph context.
1689  */
1690 
1691 static int
ng_ubt_connect(hook_p hook)1692 ng_ubt_connect(hook_p hook)
1693 {
1694 	struct ubt_softc	*sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1695 
1696 	NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1697 
1698 	UBT_NG_LOCK(sc);
1699 	ubt_task_schedule(sc, UBT_FLAG_T_START_ALL);
1700 	UBT_NG_UNLOCK(sc);
1701 
1702 	return (0);
1703 } /* ng_ubt_connect */
1704 
1705 /*
1706  * Disconnect hook.
1707  * Netgraph context.
1708  */
1709 
1710 static int
ng_ubt_disconnect(hook_p hook)1711 ng_ubt_disconnect(hook_p hook)
1712 {
1713 	struct ubt_softc	*sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1714 
1715 	UBT_NG_LOCK(sc);
1716 
1717 	if (hook != sc->sc_hook) {
1718 		UBT_NG_UNLOCK(sc);
1719 
1720 		return (EINVAL);
1721 	}
1722 
1723 	sc->sc_hook = NULL;
1724 
1725 	/* Kick off task to stop all USB xfers */
1726 	ubt_task_schedule(sc, UBT_FLAG_T_STOP_ALL);
1727 
1728 	/* Drain queues */
1729 	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1730 	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1731 	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1732 
1733 	UBT_NG_UNLOCK(sc);
1734 
1735 	return (0);
1736 } /* ng_ubt_disconnect */
1737 
1738 /*
1739  * Process control message.
1740  * Netgraph context.
1741  */
1742 
1743 static int
ng_ubt_rcvmsg(node_p node,item_p item,hook_p lasthook)1744 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
1745 {
1746 	struct ubt_softc	*sc = NG_NODE_PRIVATE(node);
1747 	struct ng_mesg		*msg, *rsp = NULL;
1748 	struct ng_bt_mbufq	*q;
1749 	int			error = 0, queue, qlen;
1750 
1751 	NGI_GET_MSG(item, msg);
1752 
1753 	switch (msg->header.typecookie) {
1754 	case NGM_GENERIC_COOKIE:
1755 		switch (msg->header.cmd) {
1756 		case NGM_TEXT_STATUS:
1757 			NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
1758 			if (rsp == NULL) {
1759 				error = ENOMEM;
1760 				break;
1761 			}
1762 
1763 			snprintf(rsp->data, NG_TEXTRESPONSE,
1764 				"Hook: %s\n" \
1765 				"Task flags: %#x\n" \
1766 				"Debug: %d\n" \
1767 				"CMD queue: [have:%d,max:%d]\n" \
1768 				"ACL queue: [have:%d,max:%d]\n" \
1769 				"SCO queue: [have:%d,max:%d]",
1770 				(sc->sc_hook != NULL) ? NG_UBT_HOOK : "",
1771 				sc->sc_task_flags,
1772 				sc->sc_debug,
1773 				sc->sc_cmdq.len,
1774 				sc->sc_cmdq.maxlen,
1775 				sc->sc_aclq.len,
1776 				sc->sc_aclq.maxlen,
1777 				sc->sc_scoq.len,
1778 				sc->sc_scoq.maxlen);
1779 			break;
1780 
1781 		default:
1782 			error = EINVAL;
1783 			break;
1784 		}
1785 		break;
1786 
1787 	case NGM_UBT_COOKIE:
1788 		switch (msg->header.cmd) {
1789 		case NGM_UBT_NODE_SET_DEBUG:
1790 			if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep)){
1791 				error = EMSGSIZE;
1792 				break;
1793 			}
1794 
1795 			sc->sc_debug = *((ng_ubt_node_debug_ep *) (msg->data));
1796 			break;
1797 
1798 		case NGM_UBT_NODE_GET_DEBUG:
1799 			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
1800 			    M_NOWAIT);
1801 			if (rsp == NULL) {
1802 				error = ENOMEM;
1803 				break;
1804 			}
1805 
1806 			*((ng_ubt_node_debug_ep *) (rsp->data)) = sc->sc_debug;
1807 			break;
1808 
1809 		case NGM_UBT_NODE_SET_QLEN:
1810 			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
1811 				error = EMSGSIZE;
1812 				break;
1813 			}
1814 
1815 			queue = ((ng_ubt_node_qlen_ep *) (msg->data))->queue;
1816 			qlen = ((ng_ubt_node_qlen_ep *) (msg->data))->qlen;
1817 
1818 			switch (queue) {
1819 			case NGM_UBT_NODE_QUEUE_CMD:
1820 				q = &sc->sc_cmdq;
1821 				break;
1822 
1823 			case NGM_UBT_NODE_QUEUE_ACL:
1824 				q = &sc->sc_aclq;
1825 				break;
1826 
1827 			case NGM_UBT_NODE_QUEUE_SCO:
1828 				q = &sc->sc_scoq;
1829 				break;
1830 
1831 			default:
1832 				error = EINVAL;
1833 				goto done;
1834 				/* NOT REACHED */
1835 			}
1836 
1837 			q->maxlen = qlen;
1838 			break;
1839 
1840 		case NGM_UBT_NODE_GET_QLEN:
1841 			if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
1842 				error = EMSGSIZE;
1843 				break;
1844 			}
1845 
1846 			queue = ((ng_ubt_node_qlen_ep *) (msg->data))->queue;
1847 
1848 			switch (queue) {
1849 			case NGM_UBT_NODE_QUEUE_CMD:
1850 				q = &sc->sc_cmdq;
1851 				break;
1852 
1853 			case NGM_UBT_NODE_QUEUE_ACL:
1854 				q = &sc->sc_aclq;
1855 				break;
1856 
1857 			case NGM_UBT_NODE_QUEUE_SCO:
1858 				q = &sc->sc_scoq;
1859 				break;
1860 
1861 			default:
1862 				error = EINVAL;
1863 				goto done;
1864 				/* NOT REACHED */
1865 			}
1866 
1867 			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_qlen_ep),
1868 				M_NOWAIT);
1869 			if (rsp == NULL) {
1870 				error = ENOMEM;
1871 				break;
1872 			}
1873 
1874 			((ng_ubt_node_qlen_ep *) (rsp->data))->queue = queue;
1875 			((ng_ubt_node_qlen_ep *) (rsp->data))->qlen = q->maxlen;
1876 			break;
1877 
1878 		case NGM_UBT_NODE_GET_STAT:
1879 			NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
1880 			    M_NOWAIT);
1881 			if (rsp == NULL) {
1882 				error = ENOMEM;
1883 				break;
1884 			}
1885 
1886 			bcopy(&sc->sc_stat, rsp->data,
1887 				sizeof(ng_ubt_node_stat_ep));
1888 			break;
1889 
1890 		case NGM_UBT_NODE_RESET_STAT:
1891 			UBT_STAT_RESET(sc);
1892 			break;
1893 
1894 		default:
1895 			error = EINVAL;
1896 			break;
1897 		}
1898 		break;
1899 
1900 	default:
1901 		error = EINVAL;
1902 		break;
1903 	}
1904 done:
1905 	NG_RESPOND_MSG(error, node, item, rsp);
1906 	NG_FREE_MSG(msg);
1907 
1908 	return (error);
1909 } /* ng_ubt_rcvmsg */
1910 
1911 /*
1912  * Process data.
1913  * Netgraph context.
1914  */
1915 
1916 static int
ng_ubt_rcvdata(hook_p hook,item_p item)1917 ng_ubt_rcvdata(hook_p hook, item_p item)
1918 {
1919 	struct ubt_softc	*sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1920 	struct mbuf		*m;
1921 	struct ng_bt_mbufq	*q;
1922 	int			action, error = 0;
1923 
1924 	if (hook != sc->sc_hook) {
1925 		error = EINVAL;
1926 		goto done;
1927 	}
1928 
1929 	/* Deatch mbuf and get HCI frame type */
1930 	NGI_GET_M(item, m);
1931 
1932 	/*
1933 	 * Minimal size of the HCI frame is 4 bytes: 1 byte frame type,
1934 	 * 2 bytes connection handle and at least 1 byte of length.
1935 	 * Panic on data frame that has size smaller than 4 bytes (it
1936 	 * should not happen)
1937 	 */
1938 
1939 	if (m->m_pkthdr.len < 4)
1940 		panic("HCI frame size is too small! pktlen=%d\n",
1941 			m->m_pkthdr.len);
1942 
1943 	/* Process HCI frame */
1944 	switch (*mtod(m, uint8_t *)) {	/* XXX call m_pullup ? */
1945 	case NG_HCI_CMD_PKT:
1946 		if (m->m_pkthdr.len - 1 > (int)UBT_CTRL_BUFFER_SIZE)
1947 			panic("HCI command frame size is too big! " \
1948 				"buffer size=%zd, packet len=%d\n",
1949 				UBT_CTRL_BUFFER_SIZE, m->m_pkthdr.len);
1950 
1951 		q = &sc->sc_cmdq;
1952 		action = UBT_FLAG_T_START_CTRL;
1953 		break;
1954 
1955 	case NG_HCI_ACL_DATA_PKT:
1956 		if (m->m_pkthdr.len - 1 > UBT_BULK_WRITE_BUFFER_SIZE)
1957 			panic("ACL data frame size is too big! " \
1958 				"buffer size=%d, packet len=%d\n",
1959 				UBT_BULK_WRITE_BUFFER_SIZE, m->m_pkthdr.len);
1960 
1961 		q = &sc->sc_aclq;
1962 		action = UBT_FLAG_T_START_BULK;
1963 		break;
1964 
1965 	case NG_HCI_SCO_DATA_PKT:
1966 		q = &sc->sc_scoq;
1967 		action = 0;
1968 		break;
1969 
1970 	default:
1971 		UBT_ERR(sc, "Dropping unsupported HCI frame, type=0x%02x, " \
1972 			"pktlen=%d\n", *mtod(m, uint8_t *), m->m_pkthdr.len);
1973 
1974 		NG_FREE_M(m);
1975 		error = EINVAL;
1976 		goto done;
1977 		/* NOT REACHED */
1978 	}
1979 
1980 	UBT_NG_LOCK(sc);
1981 	if (NG_BT_MBUFQ_FULL(q)) {
1982 		NG_BT_MBUFQ_DROP(q);
1983 		UBT_NG_UNLOCK(sc);
1984 
1985 		UBT_ERR(sc, "Dropping HCI frame 0x%02x, len=%d. Queue full\n",
1986 			*mtod(m, uint8_t *), m->m_pkthdr.len);
1987 
1988 		NG_FREE_M(m);
1989 	} else {
1990 		/* Loose HCI packet type, enqueue mbuf and kick off task */
1991 		m_adj(m, sizeof(uint8_t));
1992 		NG_BT_MBUFQ_ENQUEUE(q, m);
1993 		ubt_task_schedule(sc, action);
1994 		UBT_NG_UNLOCK(sc);
1995 	}
1996 done:
1997 	NG_FREE_ITEM(item);
1998 
1999 	return (error);
2000 } /* ng_ubt_rcvdata */
2001 
2002 /****************************************************************************
2003  ****************************************************************************
2004  **                              Module
2005  ****************************************************************************
2006  ****************************************************************************/
2007 
2008 /*
2009  * Load/Unload the driver module
2010  */
2011 
2012 static int
ubt_modevent(module_t mod,int event,void * data)2013 ubt_modevent(module_t mod, int event, void *data)
2014 {
2015 	int	error;
2016 
2017 	switch (event) {
2018 	case MOD_LOAD:
2019 		error = ng_newtype(&typestruct);
2020 		if (error != 0)
2021 			printf("%s: Could not register Netgraph node type, " \
2022 				"error=%d\n", NG_UBT_NODE_TYPE, error);
2023 		break;
2024 
2025 	case MOD_UNLOAD:
2026 		error = ng_rmtype(&typestruct);
2027 		break;
2028 
2029 	default:
2030 		error = EOPNOTSUPP;
2031 		break;
2032 	}
2033 
2034 	return (error);
2035 } /* ubt_modevent */
2036 
2037 static device_method_t	ubt_methods[] =
2038 {
2039 	DEVMETHOD(device_probe,	ubt_probe),
2040 	DEVMETHOD(device_attach, ubt_attach),
2041 	DEVMETHOD(device_detach, ubt_detach),
2042 	DEVMETHOD_END
2043 };
2044 
2045 driver_t		ubt_driver =
2046 {
2047 	.name =	   "ubt",
2048 	.methods = ubt_methods,
2049 	.size =	   sizeof(struct ubt_softc),
2050 };
2051 
2052 DRIVER_MODULE(ng_ubt, uhub, ubt_driver, ubt_modevent, 0);
2053 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
2054 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
2055 MODULE_DEPEND(ng_ubt, ng_hci, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION);
2056 MODULE_DEPEND(ng_ubt, ng_bluetooth, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION);
2057 MODULE_DEPEND(ng_ubt, usb, 1, 1, 1);
2058 USB_PNP_HOST_INFO(ubt_devs);
2059