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