blob: 6bdf593081d8d23f20dc0a5692c8dfec6d29390a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 HCI USB driver for Linux Bluetooth protocol stack (BlueZ)
3 Copyright (C) 2000-2001 Qualcomm Incorporated
4 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
5
6 Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 2 as
10 published by the Free Software Foundation;
11
12 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
13 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
15 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
16 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
17 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
21 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
22 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
23 SOFTWARE IS DISCLAIMED.
24*/
25
26/*
27 * Bluetooth HCI USB driver.
28 * Based on original USB Bluetooth driver for Linux kernel
29 * Copyright (c) 2000 Greg Kroah-Hartman <greg@kroah.com>
30 * Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu>
31 *
32 */
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/module.h>
35
36#include <linux/kernel.h>
37#include <linux/init.h>
38#include <linux/sched.h>
39#include <linux/unistd.h>
40#include <linux/types.h>
41#include <linux/interrupt.h>
42#include <linux/moduleparam.h>
43
44#include <linux/slab.h>
45#include <linux/errno.h>
46#include <linux/string.h>
47#include <linux/skbuff.h>
48
49#include <linux/usb.h>
50
51#include <net/bluetooth/bluetooth.h>
52#include <net/bluetooth/hci_core.h>
53
54#include "hci_usb.h"
55
56#ifndef CONFIG_BT_HCIUSB_DEBUG
57#undef BT_DBG
58#define BT_DBG(D...)
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#endif
60
61#ifndef CONFIG_BT_HCIUSB_ZERO_PACKET
62#undef URB_ZERO_PACKET
63#define URB_ZERO_PACKET 0
64#endif
65
66static int ignore = 0;
Marcel Holtmann7ef934b2005-11-08 09:57:05 -080067static int ignore_dga = 0;
Marcel Holtmann0915e882005-09-13 01:32:37 +020068static int ignore_csr = 0;
69static int ignore_sniffer = 0;
Marcel Holtmann520ca782006-07-14 16:01:52 +020070static int disable_scofix = 0;
71static int force_scofix = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072static int reset = 0;
73
74#ifdef CONFIG_BT_HCIUSB_SCO
75static int isoc = 2;
76#endif
77
Marcel Holtmann0915e882005-09-13 01:32:37 +020078#define VERSION "2.9"
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
80static struct usb_driver hci_usb_driver;
81
82static struct usb_device_id bluetooth_ids[] = {
83 /* Generic Bluetooth USB device */
84 { USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) },
85
86 /* AVM BlueFRITZ! USB v2.0 */
87 { USB_DEVICE(0x057c, 0x3800) },
88
89 /* Bluetooth Ultraport Module from IBM */
90 { USB_DEVICE(0x04bf, 0x030a) },
91
92 /* ALPS Modules with non-standard id */
93 { USB_DEVICE(0x044e, 0x3001) },
94 { USB_DEVICE(0x044e, 0x3002) },
95
96 /* Ericsson with non-standard id */
97 { USB_DEVICE(0x0bdb, 0x1002) },
98
Marcel Holtmann62ae1592006-09-21 16:19:55 +020099 /* Canyon CN-BTU1 with HID interfaces */
100 { USB_DEVICE(0x0c10, 0x0000), .driver_info = HCI_RESET },
101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 { } /* Terminating entry */
103};
104
105MODULE_DEVICE_TABLE (usb, bluetooth_ids);
106
107static struct usb_device_id blacklist_ids[] = {
Marcel Holtmann0915e882005-09-13 01:32:37 +0200108 /* CSR BlueCore devices */
109 { USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR },
110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 /* Broadcom BCM2033 without firmware */
112 { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
113
114 /* Broadcom BCM2035 */
Marcel Holtmanne9e92902006-07-18 18:32:33 +0200115 { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 { USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_BCM92035 },
117
Marcel Holtmann520ca782006-07-14 16:01:52 +0200118 /* IBM/Lenovo ThinkPad with Broadcom chip */
119 { USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU },
Marcel Holtmann5939be42007-01-08 02:16:46 +0100120 { USB_DEVICE(0x0a5c, 0x2110), .driver_info = HCI_WRONG_SCO_MTU },
Marcel Holtmann520ca782006-07-14 16:01:52 +0200121
Marcel Holtmann0eab9342006-10-20 08:55:29 +0200122 /* ANYCOM Bluetooth USB-200 and USB-250 */
123 { USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
124
Marcel Holtmannda942702007-01-08 02:16:50 +0100125 /* HP laptop with Broadcom chip */
126 { USB_DEVICE(0x03f0, 0x171d), .driver_info = HCI_WRONG_SCO_MTU },
127
Marcel Holtmann86112ff2007-01-08 02:16:53 +0100128 /* Dell laptop with Broadcom chip */
129 { USB_DEVICE(0x413c, 0x8126), .driver_info = HCI_WRONG_SCO_MTU },
130
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 /* Microsoft Wireless Transceiver for Bluetooth 2.0 */
132 { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
133
Marcel Holtmanncad0f622005-08-06 12:36:36 +0200134 /* Kensington Bluetooth USB adapter */
135 { USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET },
Olivier Galibert71c83512006-12-19 13:15:25 -0800136 { USB_DEVICE(0x047d, 0x105e), .driver_info = HCI_WRONG_SCO_MTU },
Marcel Holtmanncad0f622005-08-06 12:36:36 +0200137
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 /* ISSC Bluetooth Adapter v3.1 */
139 { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
140
Marcel Holtmann8e4f7232006-07-18 18:04:59 +0200141 /* RTX Telecom based adapters with buggy SCO support */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 { USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC },
Marcel Holtmann8e4f7232006-07-18 18:04:59 +0200143 { USB_DEVICE(0x0400, 0x080a), .driver_info = HCI_BROKEN_ISOC },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
Marcel Holtmannea9727f2006-07-18 17:47:40 +0200145 /* Belkin F8T012 and F8T013 devices */
Marcel Holtmannda1f5192006-07-03 10:02:29 +0200146 { USB_DEVICE(0x050d, 0x0012), .driver_info = HCI_WRONG_SCO_MTU },
Marcel Holtmannea9727f2006-07-18 17:47:40 +0200147 { USB_DEVICE(0x050d, 0x0013), .driver_info = HCI_WRONG_SCO_MTU },
Marcel Holtmannda1f5192006-07-03 10:02:29 +0200148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 /* Digianswer devices */
150 { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
151 { USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE },
152
153 /* CSR BlueCore Bluetooth Sniffer */
154 { USB_DEVICE(0x0a12, 0x0002), .driver_info = HCI_SNIFFER },
155
Marcel Holtmann2b86ad22006-07-03 10:02:18 +0200156 /* Frontline ComProbe Bluetooth Sniffer */
157 { USB_DEVICE(0x16d3, 0x0002), .driver_info = HCI_SNIFFER },
158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 { } /* Terminating entry */
160};
161
Al Virodd0fc662005-10-07 07:46:04 +0100162static struct _urb *_urb_alloc(int isoc, gfp_t gfp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163{
164 struct _urb *_urb = kmalloc(sizeof(struct _urb) +
165 sizeof(struct usb_iso_packet_descriptor) * isoc, gfp);
166 if (_urb) {
167 memset(_urb, 0, sizeof(*_urb));
168 usb_init_urb(&_urb->urb);
169 }
170 return _urb;
171}
172
173static struct _urb *_urb_dequeue(struct _urb_queue *q)
174{
175 struct _urb *_urb = NULL;
176 unsigned long flags;
177 spin_lock_irqsave(&q->lock, flags);
178 {
179 struct list_head *head = &q->head;
180 struct list_head *next = head->next;
181 if (next != head) {
182 _urb = list_entry(next, struct _urb, list);
183 list_del(next); _urb->queue = NULL;
184 }
185 }
186 spin_unlock_irqrestore(&q->lock, flags);
187 return _urb;
188}
189
David Howells7d12e782006-10-05 14:55:46 +0100190static void hci_usb_rx_complete(struct urb *urb);
191static void hci_usb_tx_complete(struct urb *urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193#define __pending_tx(husb, type) (&husb->pending_tx[type-1])
194#define __pending_q(husb, type) (&husb->pending_q[type-1])
195#define __completed_q(husb, type) (&husb->completed_q[type-1])
196#define __transmit_q(husb, type) (&husb->transmit_q[type-1])
197#define __reassembly(husb, type) (husb->reassembly[type-1])
198
199static inline struct _urb *__get_completed(struct hci_usb *husb, int type)
200{
201 return _urb_dequeue(__completed_q(husb, type));
202}
203
204#ifdef CONFIG_BT_HCIUSB_SCO
205static void __fill_isoc_desc(struct urb *urb, int len, int mtu)
206{
207 int offset = 0, i;
208
209 BT_DBG("len %d mtu %d", len, mtu);
210
211 for (i=0; i < HCI_MAX_ISOC_FRAMES && len >= mtu; i++, offset += mtu, len -= mtu) {
212 urb->iso_frame_desc[i].offset = offset;
213 urb->iso_frame_desc[i].length = mtu;
214 BT_DBG("desc %d offset %d len %d", i, offset, mtu);
215 }
216 if (len && i < HCI_MAX_ISOC_FRAMES) {
217 urb->iso_frame_desc[i].offset = offset;
218 urb->iso_frame_desc[i].length = len;
219 BT_DBG("desc %d offset %d len %d", i, offset, len);
220 i++;
221 }
222 urb->number_of_packets = i;
223}
224#endif
225
226static int hci_usb_intr_rx_submit(struct hci_usb *husb)
227{
228 struct _urb *_urb;
229 struct urb *urb;
230 int err, pipe, interval, size;
231 void *buf;
232
233 BT_DBG("%s", husb->hdev->name);
234
235 size = le16_to_cpu(husb->intr_in_ep->desc.wMaxPacketSize);
236
237 buf = kmalloc(size, GFP_ATOMIC);
238 if (!buf)
239 return -ENOMEM;
240
241 _urb = _urb_alloc(0, GFP_ATOMIC);
242 if (!_urb) {
243 kfree(buf);
244 return -ENOMEM;
245 }
246 _urb->type = HCI_EVENT_PKT;
247 _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
248
249 urb = &_urb->urb;
250 pipe = usb_rcvintpipe(husb->udev, husb->intr_in_ep->desc.bEndpointAddress);
251 interval = husb->intr_in_ep->desc.bInterval;
252 usb_fill_int_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb, interval);
253
254 err = usb_submit_urb(urb, GFP_ATOMIC);
255 if (err) {
256 BT_ERR("%s intr rx submit failed urb %p err %d",
257 husb->hdev->name, urb, err);
258 _urb_unlink(_urb);
259 _urb_free(_urb);
260 kfree(buf);
261 }
262 return err;
263}
264
265static int hci_usb_bulk_rx_submit(struct hci_usb *husb)
266{
267 struct _urb *_urb;
268 struct urb *urb;
269 int err, pipe, size = HCI_MAX_FRAME_SIZE;
270 void *buf;
271
272 buf = kmalloc(size, GFP_ATOMIC);
273 if (!buf)
274 return -ENOMEM;
275
276 _urb = _urb_alloc(0, GFP_ATOMIC);
277 if (!_urb) {
278 kfree(buf);
279 return -ENOMEM;
280 }
281 _urb->type = HCI_ACLDATA_PKT;
282 _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
283
284 urb = &_urb->urb;
285 pipe = usb_rcvbulkpipe(husb->udev, husb->bulk_in_ep->desc.bEndpointAddress);
286 usb_fill_bulk_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb);
287 urb->transfer_flags = 0;
288
289 BT_DBG("%s urb %p", husb->hdev->name, urb);
290
291 err = usb_submit_urb(urb, GFP_ATOMIC);
292 if (err) {
293 BT_ERR("%s bulk rx submit failed urb %p err %d",
294 husb->hdev->name, urb, err);
295 _urb_unlink(_urb);
296 _urb_free(_urb);
297 kfree(buf);
298 }
299 return err;
300}
301
302#ifdef CONFIG_BT_HCIUSB_SCO
303static int hci_usb_isoc_rx_submit(struct hci_usb *husb)
304{
305 struct _urb *_urb;
306 struct urb *urb;
307 int err, mtu, size;
308 void *buf;
309
310 mtu = le16_to_cpu(husb->isoc_in_ep->desc.wMaxPacketSize);
311 size = mtu * HCI_MAX_ISOC_FRAMES;
312
313 buf = kmalloc(size, GFP_ATOMIC);
314 if (!buf)
315 return -ENOMEM;
316
317 _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
318 if (!_urb) {
319 kfree(buf);
320 return -ENOMEM;
321 }
322 _urb->type = HCI_SCODATA_PKT;
323 _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
324
325 urb = &_urb->urb;
326
327 urb->context = husb;
328 urb->dev = husb->udev;
329 urb->pipe = usb_rcvisocpipe(husb->udev, husb->isoc_in_ep->desc.bEndpointAddress);
330 urb->complete = hci_usb_rx_complete;
331
332 urb->interval = husb->isoc_in_ep->desc.bInterval;
333
334 urb->transfer_buffer_length = size;
335 urb->transfer_buffer = buf;
336 urb->transfer_flags = URB_ISO_ASAP;
337
338 __fill_isoc_desc(urb, size, mtu);
339
340 BT_DBG("%s urb %p", husb->hdev->name, urb);
341
342 err = usb_submit_urb(urb, GFP_ATOMIC);
343 if (err) {
344 BT_ERR("%s isoc rx submit failed urb %p err %d",
345 husb->hdev->name, urb, err);
346 _urb_unlink(_urb);
347 _urb_free(_urb);
348 kfree(buf);
349 }
350 return err;
351}
352#endif
353
354/* Initialize device */
355static int hci_usb_open(struct hci_dev *hdev)
356{
357 struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
358 int i, err;
359 unsigned long flags;
360
361 BT_DBG("%s", hdev->name);
362
363 if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
364 return 0;
365
366 write_lock_irqsave(&husb->completion_lock, flags);
367
368 err = hci_usb_intr_rx_submit(husb);
369 if (!err) {
370 for (i = 0; i < HCI_MAX_BULK_RX; i++)
371 hci_usb_bulk_rx_submit(husb);
372
373#ifdef CONFIG_BT_HCIUSB_SCO
374 if (husb->isoc_iface)
375 for (i = 0; i < HCI_MAX_ISOC_RX; i++)
376 hci_usb_isoc_rx_submit(husb);
377#endif
378 } else {
379 clear_bit(HCI_RUNNING, &hdev->flags);
380 }
381
382 write_unlock_irqrestore(&husb->completion_lock, flags);
383 return err;
384}
385
386/* Reset device */
387static int hci_usb_flush(struct hci_dev *hdev)
388{
389 struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
390 int i;
391
392 BT_DBG("%s", hdev->name);
393
394 for (i = 0; i < 4; i++)
395 skb_queue_purge(&husb->transmit_q[i]);
396 return 0;
397}
398
399static void hci_usb_unlink_urbs(struct hci_usb *husb)
400{
401 int i;
402
403 BT_DBG("%s", husb->hdev->name);
404
405 for (i = 0; i < 4; i++) {
406 struct _urb *_urb;
407 struct urb *urb;
408
409 /* Kill pending requests */
410 while ((_urb = _urb_dequeue(&husb->pending_q[i]))) {
411 urb = &_urb->urb;
412 BT_DBG("%s unlinking _urb %p type %d urb %p",
413 husb->hdev->name, _urb, _urb->type, urb);
414 usb_kill_urb(urb);
415 _urb_queue_tail(__completed_q(husb, _urb->type), _urb);
416 }
417
418 /* Release completed requests */
419 while ((_urb = _urb_dequeue(&husb->completed_q[i]))) {
420 urb = &_urb->urb;
421 BT_DBG("%s freeing _urb %p type %d urb %p",
422 husb->hdev->name, _urb, _urb->type, urb);
Marcel Holtmanne9a3e672005-08-06 12:36:47 +0200423 kfree(urb->setup_packet);
424 kfree(urb->transfer_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 _urb_free(_urb);
426 }
427
428 /* Release reassembly buffers */
429 if (husb->reassembly[i]) {
430 kfree_skb(husb->reassembly[i]);
431 husb->reassembly[i] = NULL;
432 }
433 }
434}
435
436/* Close device */
437static int hci_usb_close(struct hci_dev *hdev)
438{
439 struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
440 unsigned long flags;
441
442 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
443 return 0;
444
445 BT_DBG("%s", hdev->name);
446
447 /* Synchronize with completion handlers */
448 write_lock_irqsave(&husb->completion_lock, flags);
449 write_unlock_irqrestore(&husb->completion_lock, flags);
450
451 hci_usb_unlink_urbs(husb);
452 hci_usb_flush(hdev);
453 return 0;
454}
455
456static int __tx_submit(struct hci_usb *husb, struct _urb *_urb)
457{
458 struct urb *urb = &_urb->urb;
459 int err;
460
461 BT_DBG("%s urb %p type %d", husb->hdev->name, urb, _urb->type);
462
463 _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
464 err = usb_submit_urb(urb, GFP_ATOMIC);
465 if (err) {
466 BT_ERR("%s tx submit failed urb %p type %d err %d",
467 husb->hdev->name, urb, _urb->type, err);
468 _urb_unlink(_urb);
469 _urb_queue_tail(__completed_q(husb, _urb->type), _urb);
470 } else
471 atomic_inc(__pending_tx(husb, _urb->type));
472
473 return err;
474}
475
476static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
477{
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700478 struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 struct usb_ctrlrequest *dr;
480 struct urb *urb;
481
482 if (!_urb) {
483 _urb = _urb_alloc(0, GFP_ATOMIC);
484 if (!_urb)
485 return -ENOMEM;
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700486 _urb->type = bt_cb(skb)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
489 if (!dr) {
490 _urb_free(_urb);
491 return -ENOMEM;
492 }
493 } else
494 dr = (void *) _urb->urb.setup_packet;
495
496 dr->bRequestType = husb->ctrl_req;
497 dr->bRequest = 0;
498 dr->wIndex = 0;
499 dr->wValue = 0;
500 dr->wLength = __cpu_to_le16(skb->len);
501
502 urb = &_urb->urb;
503 usb_fill_control_urb(urb, husb->udev, usb_sndctrlpipe(husb->udev, 0),
504 (void *) dr, skb->data, skb->len, hci_usb_tx_complete, husb);
505
506 BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
507
508 _urb->priv = skb;
509 return __tx_submit(husb, _urb);
510}
511
512static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
513{
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700514 struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 struct urb *urb;
516 int pipe;
517
518 if (!_urb) {
519 _urb = _urb_alloc(0, GFP_ATOMIC);
520 if (!_urb)
521 return -ENOMEM;
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700522 _urb->type = bt_cb(skb)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 }
524
525 urb = &_urb->urb;
526 pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep->desc.bEndpointAddress);
527 usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, skb->len,
528 hci_usb_tx_complete, husb);
529 urb->transfer_flags = URB_ZERO_PACKET;
530
531 BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
532
533 _urb->priv = skb;
534 return __tx_submit(husb, _urb);
535}
536
537#ifdef CONFIG_BT_HCIUSB_SCO
538static inline int hci_usb_send_isoc(struct hci_usb *husb, struct sk_buff *skb)
539{
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700540 struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 struct urb *urb;
542
543 if (!_urb) {
544 _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
545 if (!_urb)
546 return -ENOMEM;
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700547 _urb->type = bt_cb(skb)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 }
549
550 BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
551
552 urb = &_urb->urb;
553
554 urb->context = husb;
555 urb->dev = husb->udev;
556 urb->pipe = usb_sndisocpipe(husb->udev, husb->isoc_out_ep->desc.bEndpointAddress);
557 urb->complete = hci_usb_tx_complete;
558 urb->transfer_flags = URB_ISO_ASAP;
559
560 urb->interval = husb->isoc_out_ep->desc.bInterval;
561
562 urb->transfer_buffer = skb->data;
563 urb->transfer_buffer_length = skb->len;
564
565 __fill_isoc_desc(urb, skb->len, le16_to_cpu(husb->isoc_out_ep->desc.wMaxPacketSize));
566
567 _urb->priv = skb;
568 return __tx_submit(husb, _urb);
569}
570#endif
571
572static void hci_usb_tx_process(struct hci_usb *husb)
573{
574 struct sk_buff_head *q;
575 struct sk_buff *skb;
576
577 BT_DBG("%s", husb->hdev->name);
578
579 do {
580 clear_bit(HCI_USB_TX_WAKEUP, &husb->state);
581
582 /* Process command queue */
583 q = __transmit_q(husb, HCI_COMMAND_PKT);
584 if (!atomic_read(__pending_tx(husb, HCI_COMMAND_PKT)) &&
585 (skb = skb_dequeue(q))) {
586 if (hci_usb_send_ctrl(husb, skb) < 0)
587 skb_queue_head(q, skb);
588 }
589
590#ifdef CONFIG_BT_HCIUSB_SCO
591 /* Process SCO queue */
592 q = __transmit_q(husb, HCI_SCODATA_PKT);
593 if (atomic_read(__pending_tx(husb, HCI_SCODATA_PKT)) < HCI_MAX_ISOC_TX &&
594 (skb = skb_dequeue(q))) {
595 if (hci_usb_send_isoc(husb, skb) < 0)
596 skb_queue_head(q, skb);
597 }
598#endif
599
600 /* Process ACL queue */
601 q = __transmit_q(husb, HCI_ACLDATA_PKT);
602 while (atomic_read(__pending_tx(husb, HCI_ACLDATA_PKT)) < HCI_MAX_BULK_TX &&
603 (skb = skb_dequeue(q))) {
604 if (hci_usb_send_bulk(husb, skb) < 0) {
605 skb_queue_head(q, skb);
606 break;
607 }
608 }
609 } while(test_bit(HCI_USB_TX_WAKEUP, &husb->state));
610}
611
612static inline void hci_usb_tx_wakeup(struct hci_usb *husb)
613{
614 /* Serialize TX queue processing to avoid data reordering */
615 if (!test_and_set_bit(HCI_USB_TX_PROCESS, &husb->state)) {
616 hci_usb_tx_process(husb);
617 clear_bit(HCI_USB_TX_PROCESS, &husb->state);
618 } else
619 set_bit(HCI_USB_TX_WAKEUP, &husb->state);
620}
621
622/* Send frames from HCI layer */
623static int hci_usb_send_frame(struct sk_buff *skb)
624{
625 struct hci_dev *hdev = (struct hci_dev *) skb->dev;
626 struct hci_usb *husb;
627
628 if (!hdev) {
629 BT_ERR("frame for uknown device (hdev=NULL)");
630 return -ENODEV;
631 }
632
633 if (!test_bit(HCI_RUNNING, &hdev->flags))
634 return -EBUSY;
635
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700636 BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
638 husb = (struct hci_usb *) hdev->driver_data;
639
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700640 switch (bt_cb(skb)->pkt_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 case HCI_COMMAND_PKT:
642 hdev->stat.cmd_tx++;
643 break;
644
645 case HCI_ACLDATA_PKT:
646 hdev->stat.acl_tx++;
647 break;
648
649#ifdef CONFIG_BT_HCIUSB_SCO
650 case HCI_SCODATA_PKT:
651 hdev->stat.sco_tx++;
652 break;
653#endif
654
655 default:
656 kfree_skb(skb);
657 return 0;
658 }
659
660 read_lock(&husb->completion_lock);
661
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700662 skb_queue_tail(__transmit_q(husb, bt_cb(skb)->pkt_type), skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 hci_usb_tx_wakeup(husb);
664
665 read_unlock(&husb->completion_lock);
666 return 0;
667}
668
669static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int count)
670{
671 BT_DBG("%s type %d data %p count %d", husb->hdev->name, type, data, count);
672
673 husb->hdev->stat.byte_rx += count;
674
675 while (count) {
676 struct sk_buff *skb = __reassembly(husb, type);
677 struct { int expect; } *scb;
678 int len = 0;
679
680 if (!skb) {
681 /* Start of the frame */
682
683 switch (type) {
684 case HCI_EVENT_PKT:
685 if (count >= HCI_EVENT_HDR_SIZE) {
686 struct hci_event_hdr *h = data;
687 len = HCI_EVENT_HDR_SIZE + h->plen;
688 } else
689 return -EILSEQ;
690 break;
691
692 case HCI_ACLDATA_PKT:
693 if (count >= HCI_ACL_HDR_SIZE) {
694 struct hci_acl_hdr *h = data;
695 len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
696 } else
697 return -EILSEQ;
698 break;
699#ifdef CONFIG_BT_HCIUSB_SCO
700 case HCI_SCODATA_PKT:
701 if (count >= HCI_SCO_HDR_SIZE) {
702 struct hci_sco_hdr *h = data;
703 len = HCI_SCO_HDR_SIZE + h->dlen;
704 } else
705 return -EILSEQ;
706 break;
707#endif
708 }
709 BT_DBG("new packet len %d", len);
710
711 skb = bt_skb_alloc(len, GFP_ATOMIC);
712 if (!skb) {
713 BT_ERR("%s no memory for the packet", husb->hdev->name);
714 return -ENOMEM;
715 }
716 skb->dev = (void *) husb->hdev;
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700717 bt_cb(skb)->pkt_type = type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
719 __reassembly(husb, type) = skb;
720
721 scb = (void *) skb->cb;
722 scb->expect = len;
723 } else {
724 /* Continuation */
725 scb = (void *) skb->cb;
726 len = scb->expect;
727 }
728
729 len = min(len, count);
730
731 memcpy(skb_put(skb, len), data, len);
732
733 scb->expect -= len;
734 if (!scb->expect) {
735 /* Complete frame */
736 __reassembly(husb, type) = NULL;
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700737 bt_cb(skb)->pkt_type = type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 hci_recv_frame(skb);
739 }
740
741 count -= len; data += len;
742 }
743 return 0;
744}
745
David Howells7d12e782006-10-05 14:55:46 +0100746static void hci_usb_rx_complete(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747{
748 struct _urb *_urb = container_of(urb, struct _urb, urb);
749 struct hci_usb *husb = (void *) urb->context;
750 struct hci_dev *hdev = husb->hdev;
751 int err, count = urb->actual_length;
752
753 BT_DBG("%s urb %p type %d status %d count %d flags %x", hdev->name, urb,
754 _urb->type, urb->status, count, urb->transfer_flags);
755
756 read_lock(&husb->completion_lock);
757
758 if (!test_bit(HCI_RUNNING, &hdev->flags))
759 goto unlock;
760
761 if (urb->status || !count)
762 goto resubmit;
763
764 if (_urb->type == HCI_SCODATA_PKT) {
765#ifdef CONFIG_BT_HCIUSB_SCO
766 int i;
767 for (i=0; i < urb->number_of_packets; i++) {
768 BT_DBG("desc %d status %d offset %d len %d", i,
769 urb->iso_frame_desc[i].status,
770 urb->iso_frame_desc[i].offset,
771 urb->iso_frame_desc[i].actual_length);
772
773 if (!urb->iso_frame_desc[i].status)
774 __recv_frame(husb, _urb->type,
775 urb->transfer_buffer + urb->iso_frame_desc[i].offset,
776 urb->iso_frame_desc[i].actual_length);
777 }
778#else
779 ;
780#endif
781 } else {
782 err = __recv_frame(husb, _urb->type, urb->transfer_buffer, count);
783 if (err < 0) {
784 BT_ERR("%s corrupted packet: type %d count %d",
785 husb->hdev->name, _urb->type, count);
786 hdev->stat.err_rx++;
787 }
788 }
789
790resubmit:
791 urb->dev = husb->udev;
792 err = usb_submit_urb(urb, GFP_ATOMIC);
793 BT_DBG("%s urb %p type %d resubmit status %d", hdev->name, urb,
794 _urb->type, err);
795
796unlock:
797 read_unlock(&husb->completion_lock);
798}
799
David Howells7d12e782006-10-05 14:55:46 +0100800static void hci_usb_tx_complete(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801{
802 struct _urb *_urb = container_of(urb, struct _urb, urb);
803 struct hci_usb *husb = (void *) urb->context;
804 struct hci_dev *hdev = husb->hdev;
805
806 BT_DBG("%s urb %p status %d flags %x", hdev->name, urb,
807 urb->status, urb->transfer_flags);
808
809 atomic_dec(__pending_tx(husb, _urb->type));
810
811 urb->transfer_buffer = NULL;
812 kfree_skb((struct sk_buff *) _urb->priv);
813
814 if (!test_bit(HCI_RUNNING, &hdev->flags))
815 return;
816
817 if (!urb->status)
818 hdev->stat.byte_tx += urb->transfer_buffer_length;
819 else
820 hdev->stat.err_tx++;
821
822 read_lock(&husb->completion_lock);
823
824 _urb_unlink(_urb);
825 _urb_queue_tail(__completed_q(husb, _urb->type), _urb);
826
827 hci_usb_tx_wakeup(husb);
828
829 read_unlock(&husb->completion_lock);
830}
831
832static void hci_usb_destruct(struct hci_dev *hdev)
833{
834 struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
835
836 BT_DBG("%s", hdev->name);
837
838 kfree(husb);
839}
840
841static void hci_usb_notify(struct hci_dev *hdev, unsigned int evt)
842{
843 BT_DBG("%s evt %d", hdev->name, evt);
844}
845
846static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
847{
848 struct usb_device *udev = interface_to_usbdev(intf);
849 struct usb_host_endpoint *bulk_out_ep = NULL;
850 struct usb_host_endpoint *bulk_in_ep = NULL;
851 struct usb_host_endpoint *intr_in_ep = NULL;
852 struct usb_host_endpoint *ep;
853 struct usb_host_interface *uif;
854 struct usb_interface *isoc_iface;
855 struct hci_usb *husb;
856 struct hci_dev *hdev;
857 int i, e, size, isoc_ifnum, isoc_alts;
858
859 BT_DBG("udev %p intf %p", udev, intf);
860
861 if (!id->driver_info) {
862 const struct usb_device_id *match;
863 match = usb_match_id(intf, blacklist_ids);
864 if (match)
865 id = match;
866 }
867
868 if (ignore || id->driver_info & HCI_IGNORE)
869 return -ENODEV;
870
Marcel Holtmann7ef934b2005-11-08 09:57:05 -0800871 if (ignore_dga && id->driver_info & HCI_DIGIANSWER)
872 return -ENODEV;
873
Marcel Holtmann0915e882005-09-13 01:32:37 +0200874 if (ignore_csr && id->driver_info & HCI_CSR)
875 return -ENODEV;
876
877 if (ignore_sniffer && id->driver_info & HCI_SNIFFER)
878 return -ENODEV;
879
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
881 return -ENODEV;
882
883 /* Find endpoints that we need */
884 uif = intf->cur_altsetting;
885 for (e = 0; e < uif->desc.bNumEndpoints; e++) {
886 ep = &uif->endpoint[e];
887
888 switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
889 case USB_ENDPOINT_XFER_INT:
890 if (ep->desc.bEndpointAddress & USB_DIR_IN)
891 intr_in_ep = ep;
892 break;
893
894 case USB_ENDPOINT_XFER_BULK:
895 if (ep->desc.bEndpointAddress & USB_DIR_IN)
896 bulk_in_ep = ep;
897 else
898 bulk_out_ep = ep;
899 break;
900 }
901 }
902
903 if (!bulk_in_ep || !bulk_out_ep || !intr_in_ep) {
904 BT_DBG("Bulk endpoints not found");
905 goto done;
906 }
907
Deepak Saxena089b1db2005-11-07 01:01:26 -0800908 if (!(husb = kzalloc(sizeof(struct hci_usb), GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 BT_ERR("Can't allocate: control structure");
910 goto done;
911 }
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 husb->udev = udev;
914 husb->bulk_out_ep = bulk_out_ep;
915 husb->bulk_in_ep = bulk_in_ep;
916 husb->intr_in_ep = intr_in_ep;
917
918 if (id->driver_info & HCI_DIGIANSWER)
919 husb->ctrl_req = USB_TYPE_VENDOR;
920 else
921 husb->ctrl_req = USB_TYPE_CLASS;
922
923 /* Find isochronous endpoints that we can use */
924 size = 0;
925 isoc_iface = NULL;
926 isoc_alts = 0;
927 isoc_ifnum = 1;
928
929#ifdef CONFIG_BT_HCIUSB_SCO
930 if (isoc && !(id->driver_info & (HCI_BROKEN_ISOC | HCI_SNIFFER)))
931 isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
932
933 if (isoc_iface) {
934 int a;
935 struct usb_host_endpoint *isoc_out_ep = NULL;
936 struct usb_host_endpoint *isoc_in_ep = NULL;
937
938 for (a = 0; a < isoc_iface->num_altsetting; a++) {
939 uif = &isoc_iface->altsetting[a];
940 for (e = 0; e < uif->desc.bNumEndpoints; e++) {
941 ep = &uif->endpoint[e];
942
943 switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
944 case USB_ENDPOINT_XFER_ISOC:
945 if (le16_to_cpu(ep->desc.wMaxPacketSize) < size ||
946 uif->desc.bAlternateSetting != isoc)
947 break;
948 size = le16_to_cpu(ep->desc.wMaxPacketSize);
949
950 isoc_alts = uif->desc.bAlternateSetting;
951
952 if (ep->desc.bEndpointAddress & USB_DIR_IN)
953 isoc_in_ep = ep;
954 else
955 isoc_out_ep = ep;
956 break;
957 }
958 }
959 }
960
961 if (!isoc_in_ep || !isoc_out_ep)
962 BT_DBG("Isoc endpoints not found");
963 else {
964 BT_DBG("isoc ifnum %d alts %d", isoc_ifnum, isoc_alts);
965 if (usb_driver_claim_interface(&hci_usb_driver, isoc_iface, husb) != 0)
966 BT_ERR("Can't claim isoc interface");
967 else if (usb_set_interface(udev, isoc_ifnum, isoc_alts)) {
968 BT_ERR("Can't set isoc interface settings");
969 husb->isoc_iface = isoc_iface;
970 usb_driver_release_interface(&hci_usb_driver, isoc_iface);
971 husb->isoc_iface = NULL;
972 } else {
973 husb->isoc_iface = isoc_iface;
974 husb->isoc_in_ep = isoc_in_ep;
975 husb->isoc_out_ep = isoc_out_ep;
976 }
977 }
978 }
979#endif
980
981 rwlock_init(&husb->completion_lock);
982
983 for (i = 0; i < 4; i++) {
984 skb_queue_head_init(&husb->transmit_q[i]);
985 _urb_queue_init(&husb->pending_q[i]);
986 _urb_queue_init(&husb->completed_q[i]);
987 }
988
989 /* Initialize and register HCI device */
990 hdev = hci_alloc_dev();
991 if (!hdev) {
992 BT_ERR("Can't allocate HCI device");
993 goto probe_error;
994 }
995
996 husb->hdev = hdev;
997
998 hdev->type = HCI_USB;
999 hdev->driver_data = husb;
1000 SET_HCIDEV_DEV(hdev, &intf->dev);
1001
1002 hdev->open = hci_usb_open;
1003 hdev->close = hci_usb_close;
1004 hdev->flush = hci_usb_flush;
1005 hdev->send = hci_usb_send_frame;
1006 hdev->destruct = hci_usb_destruct;
1007 hdev->notify = hci_usb_notify;
1008
1009 hdev->owner = THIS_MODULE;
1010
1011 if (reset || id->driver_info & HCI_RESET)
1012 set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
1013
Marcel Holtmann520ca782006-07-14 16:01:52 +02001014 if (force_scofix || id->driver_info & HCI_WRONG_SCO_MTU) {
1015 if (!disable_scofix)
1016 set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
1017 }
Marcel Holtmannda1f5192006-07-03 10:02:29 +02001018
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 if (id->driver_info & HCI_SNIFFER) {
1020 if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
1021 set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
1022 }
1023
1024 if (id->driver_info & HCI_BCM92035) {
1025 unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
1026 struct sk_buff *skb;
1027
1028 skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
1029 if (skb) {
1030 memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
1031 skb_queue_tail(&hdev->driver_init, skb);
1032 }
1033 }
1034
1035 if (hci_register_dev(hdev) < 0) {
1036 BT_ERR("Can't register HCI device");
1037 hci_free_dev(hdev);
1038 goto probe_error;
1039 }
1040
1041 usb_set_intfdata(intf, husb);
1042 return 0;
1043
1044probe_error:
1045 if (husb->isoc_iface)
1046 usb_driver_release_interface(&hci_usb_driver, husb->isoc_iface);
1047 kfree(husb);
1048
1049done:
1050 return -EIO;
1051}
1052
1053static void hci_usb_disconnect(struct usb_interface *intf)
1054{
1055 struct hci_usb *husb = usb_get_intfdata(intf);
1056 struct hci_dev *hdev;
1057
1058 if (!husb || intf == husb->isoc_iface)
1059 return;
1060
1061 usb_set_intfdata(intf, NULL);
1062 hdev = husb->hdev;
1063
1064 BT_DBG("%s", hdev->name);
1065
1066 hci_usb_close(hdev);
1067
1068 if (husb->isoc_iface)
1069 usb_driver_release_interface(&hci_usb_driver, husb->isoc_iface);
1070
1071 if (hci_unregister_dev(hdev) < 0)
1072 BT_ERR("Can't unregister HCI device %s", hdev->name);
1073
1074 hci_free_dev(hdev);
1075}
1076
Marcel Holtmanndcdcf632006-07-03 10:02:24 +02001077static int hci_usb_suspend(struct usb_interface *intf, pm_message_t message)
1078{
1079 struct hci_usb *husb = usb_get_intfdata(intf);
1080 struct list_head killed;
1081 unsigned long flags;
1082 int i;
1083
1084 if (!husb || intf == husb->isoc_iface)
1085 return 0;
1086
1087 hci_suspend_dev(husb->hdev);
1088
1089 INIT_LIST_HEAD(&killed);
1090
1091 for (i = 0; i < 4; i++) {
1092 struct _urb_queue *q = &husb->pending_q[i];
1093 struct _urb *_urb, *_tmp;
1094
1095 while ((_urb = _urb_dequeue(q))) {
1096 /* reset queue since _urb_dequeue sets it to NULL */
1097 _urb->queue = q;
1098 usb_kill_urb(&_urb->urb);
1099 list_add(&_urb->list, &killed);
1100 }
1101
1102 spin_lock_irqsave(&q->lock, flags);
1103
1104 list_for_each_entry_safe(_urb, _tmp, &killed, list) {
1105 list_move_tail(&_urb->list, &q->head);
1106 }
1107
1108 spin_unlock_irqrestore(&q->lock, flags);
1109 }
1110
1111 return 0;
1112}
1113
1114static int hci_usb_resume(struct usb_interface *intf)
1115{
1116 struct hci_usb *husb = usb_get_intfdata(intf);
1117 unsigned long flags;
1118 int i, err = 0;
1119
1120 if (!husb || intf == husb->isoc_iface)
1121 return 0;
1122
1123 for (i = 0; i < 4; i++) {
1124 struct _urb_queue *q = &husb->pending_q[i];
1125 struct _urb *_urb;
1126
1127 spin_lock_irqsave(&q->lock, flags);
1128
1129 list_for_each_entry(_urb, &q->head, list) {
1130 err = usb_submit_urb(&_urb->urb, GFP_ATOMIC);
1131 if (err)
1132 break;
1133 }
1134
1135 spin_unlock_irqrestore(&q->lock, flags);
1136
1137 if (err)
1138 return -EIO;
1139 }
1140
1141 hci_resume_dev(husb->hdev);
1142
1143 return 0;
1144}
1145
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146static struct usb_driver hci_usb_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 .name = "hci_usb",
1148 .probe = hci_usb_probe,
1149 .disconnect = hci_usb_disconnect,
Marcel Holtmanndcdcf632006-07-03 10:02:24 +02001150 .suspend = hci_usb_suspend,
1151 .resume = hci_usb_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 .id_table = bluetooth_ids,
1153};
1154
1155static int __init hci_usb_init(void)
1156{
1157 int err;
1158
1159 BT_INFO("HCI USB driver ver %s", VERSION);
1160
1161 if ((err = usb_register(&hci_usb_driver)) < 0)
1162 BT_ERR("Failed to register HCI USB driver");
1163
1164 return err;
1165}
1166
1167static void __exit hci_usb_exit(void)
1168{
1169 usb_deregister(&hci_usb_driver);
1170}
1171
1172module_init(hci_usb_init);
1173module_exit(hci_usb_exit);
1174
1175module_param(ignore, bool, 0644);
1176MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
1177
Marcel Holtmann7ef934b2005-11-08 09:57:05 -08001178module_param(ignore_dga, bool, 0644);
1179MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
1180
Marcel Holtmann0915e882005-09-13 01:32:37 +02001181module_param(ignore_csr, bool, 0644);
1182MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
1183
1184module_param(ignore_sniffer, bool, 0644);
1185MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
1186
Marcel Holtmann520ca782006-07-14 16:01:52 +02001187module_param(disable_scofix, bool, 0644);
1188MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
1189
1190module_param(force_scofix, bool, 0644);
1191MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size");
1192
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193module_param(reset, bool, 0644);
1194MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
1195
1196#ifdef CONFIG_BT_HCIUSB_SCO
1197module_param(isoc, int, 0644);
1198MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support");
1199#endif
1200
1201MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
1202MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION);
1203MODULE_VERSION(VERSION);
1204MODULE_LICENSE("GPL");