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