blob: 192522ebb771926e4fec2cfabc595869f6cd4bed [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <linux/unistd.h>
39#include <linux/types.h>
40#include <linux/interrupt.h>
41#include <linux/moduleparam.h>
42
43#include <linux/slab.h>
44#include <linux/errno.h>
45#include <linux/string.h>
46#include <linux/skbuff.h>
47
48#include <linux/usb.h>
49
50#include <net/bluetooth/bluetooth.h>
51#include <net/bluetooth/hci_core.h>
52
53#include "hci_usb.h"
54
55#ifndef CONFIG_BT_HCIUSB_DEBUG
56#undef BT_DBG
57#define BT_DBG(D...)
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#endif
59
60#ifndef CONFIG_BT_HCIUSB_ZERO_PACKET
61#undef URB_ZERO_PACKET
62#define URB_ZERO_PACKET 0
63#endif
64
Pavel Macheka8827112008-04-19 18:13:40 -070065static int ignore;
66static int ignore_dga;
67static int ignore_csr;
68static int ignore_sniffer;
69static int disable_scofix;
70static int force_scofix;
71static int reset;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73#ifdef CONFIG_BT_HCIUSB_SCO
74static int isoc = 2;
75#endif
76
Marcel Holtmann0915e882005-09-13 01:32:37 +020077#define VERSION "2.9"
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79static struct usb_driver hci_usb_driver;
80
81static struct usb_device_id bluetooth_ids[] = {
82 /* Generic Bluetooth USB device */
83 { USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) },
84
85 /* AVM BlueFRITZ! USB v2.0 */
86 { USB_DEVICE(0x057c, 0x3800) },
87
88 /* Bluetooth Ultraport Module from IBM */
89 { USB_DEVICE(0x04bf, 0x030a) },
90
91 /* ALPS Modules with non-standard id */
92 { USB_DEVICE(0x044e, 0x3001) },
93 { USB_DEVICE(0x044e, 0x3002) },
94
95 /* Ericsson with non-standard id */
96 { USB_DEVICE(0x0bdb, 0x1002) },
97
Marcel Holtmann62ae1592006-09-21 16:19:55 +020098 /* Canyon CN-BTU1 with HID interfaces */
99 { USB_DEVICE(0x0c10, 0x0000), .driver_info = HCI_RESET },
100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 { } /* Terminating entry */
102};
103
104MODULE_DEVICE_TABLE (usb, bluetooth_ids);
105
106static struct usb_device_id blacklist_ids[] = {
Marcel Holtmann0915e882005-09-13 01:32:37 +0200107 /* CSR BlueCore devices */
108 { USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR },
109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 /* Broadcom BCM2033 without firmware */
111 { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
112
113 /* Broadcom BCM2035 */
Andy Shevchenko6e46c8c2008-02-05 03:10:02 -0800114 { USB_DEVICE(0x0a5c, 0x2035), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
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 Holtmann7bb078c2007-05-05 00:36:22 +0200118 /* Broadcom BCM2045 */
Karsten Keil60d5bce2008-03-07 21:10:34 +0100119 { USB_DEVICE(0x0a5c, 0x2039), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
Marcel Holtmannfd184ab2007-05-24 14:26:15 +0200120 { USB_DEVICE(0x0a5c, 0x2101), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
Marcel Holtmann7bb078c2007-05-05 00:36:22 +0200121
Marcel Holtmann520ca782006-07-14 16:01:52 +0200122 /* IBM/Lenovo ThinkPad with Broadcom chip */
Marcel Holtmannfd184ab2007-05-24 14:26:15 +0200123 { USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
124 { USB_DEVICE(0x0a5c, 0x2110), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
Marcel Holtmann520ca782006-07-14 16:01:52 +0200125
Marcel Holtmannc51bd3d2007-05-05 00:36:17 +0200126 /* Targus ACB10US */
127 { USB_DEVICE(0x0a5c, 0x2100), .driver_info = HCI_RESET },
128
Marcel Holtmann0eab9342006-10-20 08:55:29 +0200129 /* ANYCOM Bluetooth USB-200 and USB-250 */
130 { USB_DEVICE(0x0a5c, 0x2111), .driver_info = HCI_RESET },
131
Marcel Holtmannda942702007-01-08 02:16:50 +0100132 /* HP laptop with Broadcom chip */
Marcel Holtmannfd184ab2007-05-24 14:26:15 +0200133 { USB_DEVICE(0x03f0, 0x171d), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
Marcel Holtmannda942702007-01-08 02:16:50 +0100134
Marcel Holtmann86112ff2007-01-08 02:16:53 +0100135 /* Dell laptop with Broadcom chip */
Marcel Holtmannfd184ab2007-05-24 14:26:15 +0200136 { USB_DEVICE(0x413c, 0x8126), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
Marcel Holtmann86112ff2007-01-08 02:16:53 +0100137
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 /* Microsoft Wireless Transceiver for Bluetooth 2.0 */
139 { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET },
140
Marcel Holtmanncad0f622005-08-06 12:36:36 +0200141 /* Kensington Bluetooth USB adapter */
142 { USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET },
Marcel Holtmannfd184ab2007-05-24 14:26:15 +0200143 { USB_DEVICE(0x047d, 0x105e), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
Marcel Holtmanncad0f622005-08-06 12:36:36 +0200144
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 /* ISSC Bluetooth Adapter v3.1 */
146 { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
147
Marcel Holtmann8e4f7232006-07-18 18:04:59 +0200148 /* RTX Telecom based adapters with buggy SCO support */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 { USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC },
Marcel Holtmann8e4f7232006-07-18 18:04:59 +0200150 { USB_DEVICE(0x0400, 0x080a), .driver_info = HCI_BROKEN_ISOC },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
SDiZ09a76032008-03-05 18:43:50 -0800152 /* CONWISE Technology based adapters with buggy SCO support */
153 { USB_DEVICE(0x0e5e, 0x6622), .driver_info = HCI_BROKEN_ISOC },
154
Marcel Holtmannea9727f2006-07-18 17:47:40 +0200155 /* Belkin F8T012 and F8T013 devices */
Marcel Holtmannfd184ab2007-05-24 14:26:15 +0200156 { USB_DEVICE(0x050d, 0x0012), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
157 { USB_DEVICE(0x050d, 0x0013), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
Marcel Holtmannda1f5192006-07-03 10:02:29 +0200158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 /* Digianswer devices */
160 { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
161 { USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE },
162
163 /* CSR BlueCore Bluetooth Sniffer */
164 { USB_DEVICE(0x0a12, 0x0002), .driver_info = HCI_SNIFFER },
165
Marcel Holtmann2b86ad22006-07-03 10:02:18 +0200166 /* Frontline ComProbe Bluetooth Sniffer */
167 { USB_DEVICE(0x16d3, 0x0002), .driver_info = HCI_SNIFFER },
168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 { } /* Terminating entry */
170};
171
Al Virodd0fc662005-10-07 07:46:04 +0100172static struct _urb *_urb_alloc(int isoc, gfp_t gfp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173{
174 struct _urb *_urb = kmalloc(sizeof(struct _urb) +
175 sizeof(struct usb_iso_packet_descriptor) * isoc, gfp);
176 if (_urb) {
177 memset(_urb, 0, sizeof(*_urb));
178 usb_init_urb(&_urb->urb);
179 }
180 return _urb;
181}
182
183static struct _urb *_urb_dequeue(struct _urb_queue *q)
184{
185 struct _urb *_urb = NULL;
186 unsigned long flags;
187 spin_lock_irqsave(&q->lock, flags);
188 {
189 struct list_head *head = &q->head;
190 struct list_head *next = head->next;
191 if (next != head) {
192 _urb = list_entry(next, struct _urb, list);
193 list_del(next); _urb->queue = NULL;
194 }
195 }
196 spin_unlock_irqrestore(&q->lock, flags);
197 return _urb;
198}
199
David Howells7d12e782006-10-05 14:55:46 +0100200static void hci_usb_rx_complete(struct urb *urb);
201static void hci_usb_tx_complete(struct urb *urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
203#define __pending_tx(husb, type) (&husb->pending_tx[type-1])
204#define __pending_q(husb, type) (&husb->pending_q[type-1])
205#define __completed_q(husb, type) (&husb->completed_q[type-1])
206#define __transmit_q(husb, type) (&husb->transmit_q[type-1])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
208static inline struct _urb *__get_completed(struct hci_usb *husb, int type)
209{
210 return _urb_dequeue(__completed_q(husb, type));
211}
212
213#ifdef CONFIG_BT_HCIUSB_SCO
214static void __fill_isoc_desc(struct urb *urb, int len, int mtu)
215{
216 int offset = 0, i;
217
218 BT_DBG("len %d mtu %d", len, mtu);
219
220 for (i=0; i < HCI_MAX_ISOC_FRAMES && len >= mtu; i++, offset += mtu, len -= mtu) {
221 urb->iso_frame_desc[i].offset = offset;
222 urb->iso_frame_desc[i].length = mtu;
223 BT_DBG("desc %d offset %d len %d", i, offset, mtu);
224 }
225 if (len && i < HCI_MAX_ISOC_FRAMES) {
226 urb->iso_frame_desc[i].offset = offset;
227 urb->iso_frame_desc[i].length = len;
228 BT_DBG("desc %d offset %d len %d", i, offset, len);
229 i++;
230 }
231 urb->number_of_packets = i;
232}
233#endif
234
235static int hci_usb_intr_rx_submit(struct hci_usb *husb)
236{
237 struct _urb *_urb;
238 struct urb *urb;
239 int err, pipe, interval, size;
240 void *buf;
241
242 BT_DBG("%s", husb->hdev->name);
243
244 size = le16_to_cpu(husb->intr_in_ep->desc.wMaxPacketSize);
245
246 buf = kmalloc(size, GFP_ATOMIC);
247 if (!buf)
248 return -ENOMEM;
249
250 _urb = _urb_alloc(0, GFP_ATOMIC);
251 if (!_urb) {
252 kfree(buf);
253 return -ENOMEM;
254 }
255 _urb->type = HCI_EVENT_PKT;
256 _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
257
258 urb = &_urb->urb;
259 pipe = usb_rcvintpipe(husb->udev, husb->intr_in_ep->desc.bEndpointAddress);
260 interval = husb->intr_in_ep->desc.bInterval;
261 usb_fill_int_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb, interval);
262
263 err = usb_submit_urb(urb, GFP_ATOMIC);
264 if (err) {
265 BT_ERR("%s intr rx submit failed urb %p err %d",
266 husb->hdev->name, urb, err);
267 _urb_unlink(_urb);
Pavel Machekd129f182008-04-19 18:17:26 -0700268 kfree(_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 kfree(buf);
270 }
271 return err;
272}
273
274static int hci_usb_bulk_rx_submit(struct hci_usb *husb)
275{
276 struct _urb *_urb;
277 struct urb *urb;
278 int err, pipe, size = HCI_MAX_FRAME_SIZE;
279 void *buf;
280
281 buf = kmalloc(size, GFP_ATOMIC);
282 if (!buf)
283 return -ENOMEM;
284
285 _urb = _urb_alloc(0, GFP_ATOMIC);
286 if (!_urb) {
287 kfree(buf);
288 return -ENOMEM;
289 }
290 _urb->type = HCI_ACLDATA_PKT;
291 _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
292
293 urb = &_urb->urb;
294 pipe = usb_rcvbulkpipe(husb->udev, husb->bulk_in_ep->desc.bEndpointAddress);
295 usb_fill_bulk_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb);
296 urb->transfer_flags = 0;
297
298 BT_DBG("%s urb %p", husb->hdev->name, urb);
299
300 err = usb_submit_urb(urb, GFP_ATOMIC);
301 if (err) {
302 BT_ERR("%s bulk rx submit failed urb %p err %d",
303 husb->hdev->name, urb, err);
304 _urb_unlink(_urb);
Pavel Machekd129f182008-04-19 18:17:26 -0700305 kfree(_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 kfree(buf);
307 }
308 return err;
309}
310
311#ifdef CONFIG_BT_HCIUSB_SCO
312static int hci_usb_isoc_rx_submit(struct hci_usb *husb)
313{
314 struct _urb *_urb;
315 struct urb *urb;
316 int err, mtu, size;
317 void *buf;
318
319 mtu = le16_to_cpu(husb->isoc_in_ep->desc.wMaxPacketSize);
320 size = mtu * HCI_MAX_ISOC_FRAMES;
321
322 buf = kmalloc(size, GFP_ATOMIC);
323 if (!buf)
324 return -ENOMEM;
325
326 _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
327 if (!_urb) {
328 kfree(buf);
329 return -ENOMEM;
330 }
331 _urb->type = HCI_SCODATA_PKT;
332 _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
333
334 urb = &_urb->urb;
335
336 urb->context = husb;
337 urb->dev = husb->udev;
338 urb->pipe = usb_rcvisocpipe(husb->udev, husb->isoc_in_ep->desc.bEndpointAddress);
339 urb->complete = hci_usb_rx_complete;
340
341 urb->interval = husb->isoc_in_ep->desc.bInterval;
342
343 urb->transfer_buffer_length = size;
344 urb->transfer_buffer = buf;
345 urb->transfer_flags = URB_ISO_ASAP;
346
347 __fill_isoc_desc(urb, size, mtu);
348
349 BT_DBG("%s urb %p", husb->hdev->name, urb);
350
351 err = usb_submit_urb(urb, GFP_ATOMIC);
352 if (err) {
353 BT_ERR("%s isoc rx submit failed urb %p err %d",
354 husb->hdev->name, urb, err);
355 _urb_unlink(_urb);
Pavel Machekd129f182008-04-19 18:17:26 -0700356 kfree(_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 kfree(buf);
358 }
359 return err;
360}
361#endif
362
363/* Initialize device */
364static int hci_usb_open(struct hci_dev *hdev)
365{
366 struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
367 int i, err;
368 unsigned long flags;
369
370 BT_DBG("%s", hdev->name);
371
372 if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
373 return 0;
374
375 write_lock_irqsave(&husb->completion_lock, flags);
376
377 err = hci_usb_intr_rx_submit(husb);
378 if (!err) {
379 for (i = 0; i < HCI_MAX_BULK_RX; i++)
380 hci_usb_bulk_rx_submit(husb);
381
382#ifdef CONFIG_BT_HCIUSB_SCO
383 if (husb->isoc_iface)
384 for (i = 0; i < HCI_MAX_ISOC_RX; i++)
385 hci_usb_isoc_rx_submit(husb);
386#endif
387 } else {
388 clear_bit(HCI_RUNNING, &hdev->flags);
389 }
390
391 write_unlock_irqrestore(&husb->completion_lock, flags);
392 return err;
393}
394
395/* Reset device */
396static int hci_usb_flush(struct hci_dev *hdev)
397{
398 struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
399 int i;
400
401 BT_DBG("%s", hdev->name);
402
403 for (i = 0; i < 4; i++)
404 skb_queue_purge(&husb->transmit_q[i]);
405 return 0;
406}
407
408static void hci_usb_unlink_urbs(struct hci_usb *husb)
409{
410 int i;
411
412 BT_DBG("%s", husb->hdev->name);
413
414 for (i = 0; i < 4; i++) {
415 struct _urb *_urb;
416 struct urb *urb;
417
418 /* Kill pending requests */
419 while ((_urb = _urb_dequeue(&husb->pending_q[i]))) {
420 urb = &_urb->urb;
421 BT_DBG("%s unlinking _urb %p type %d urb %p",
422 husb->hdev->name, _urb, _urb->type, urb);
423 usb_kill_urb(urb);
424 _urb_queue_tail(__completed_q(husb, _urb->type), _urb);
425 }
426
427 /* Release completed requests */
428 while ((_urb = _urb_dequeue(&husb->completed_q[i]))) {
429 urb = &_urb->urb;
430 BT_DBG("%s freeing _urb %p type %d urb %p",
431 husb->hdev->name, _urb, _urb->type, urb);
Marcel Holtmanne9a3e672005-08-06 12:36:47 +0200432 kfree(urb->setup_packet);
433 kfree(urb->transfer_buffer);
Pavel Machekd129f182008-04-19 18:17:26 -0700434 kfree(_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 }
437}
438
439/* Close device */
440static int hci_usb_close(struct hci_dev *hdev)
441{
442 struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
443 unsigned long flags;
444
445 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
446 return 0;
447
448 BT_DBG("%s", hdev->name);
449
450 /* Synchronize with completion handlers */
451 write_lock_irqsave(&husb->completion_lock, flags);
452 write_unlock_irqrestore(&husb->completion_lock, flags);
453
454 hci_usb_unlink_urbs(husb);
455 hci_usb_flush(hdev);
456 return 0;
457}
458
459static int __tx_submit(struct hci_usb *husb, struct _urb *_urb)
460{
461 struct urb *urb = &_urb->urb;
462 int err;
463
464 BT_DBG("%s urb %p type %d", husb->hdev->name, urb, _urb->type);
465
466 _urb_queue_tail(__pending_q(husb, _urb->type), _urb);
467 err = usb_submit_urb(urb, GFP_ATOMIC);
468 if (err) {
469 BT_ERR("%s tx submit failed urb %p type %d err %d",
470 husb->hdev->name, urb, _urb->type, err);
471 _urb_unlink(_urb);
472 _urb_queue_tail(__completed_q(husb, _urb->type), _urb);
473 } else
474 atomic_inc(__pending_tx(husb, _urb->type));
475
476 return err;
477}
478
479static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
480{
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700481 struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 struct usb_ctrlrequest *dr;
483 struct urb *urb;
484
485 if (!_urb) {
486 _urb = _urb_alloc(0, GFP_ATOMIC);
487 if (!_urb)
488 return -ENOMEM;
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700489 _urb->type = bt_cb(skb)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
491 dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
492 if (!dr) {
Pavel Machekd129f182008-04-19 18:17:26 -0700493 kfree(_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 return -ENOMEM;
495 }
496 } else
497 dr = (void *) _urb->urb.setup_packet;
498
499 dr->bRequestType = husb->ctrl_req;
500 dr->bRequest = 0;
501 dr->wIndex = 0;
502 dr->wValue = 0;
503 dr->wLength = __cpu_to_le16(skb->len);
504
505 urb = &_urb->urb;
506 usb_fill_control_urb(urb, husb->udev, usb_sndctrlpipe(husb->udev, 0),
507 (void *) dr, skb->data, skb->len, hci_usb_tx_complete, husb);
508
509 BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
510
511 _urb->priv = skb;
512 return __tx_submit(husb, _urb);
513}
514
515static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb)
516{
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700517 struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 struct urb *urb;
519 int pipe;
520
521 if (!_urb) {
522 _urb = _urb_alloc(0, GFP_ATOMIC);
523 if (!_urb)
524 return -ENOMEM;
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700525 _urb->type = bt_cb(skb)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 }
527
528 urb = &_urb->urb;
529 pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep->desc.bEndpointAddress);
530 usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, skb->len,
531 hci_usb_tx_complete, husb);
532 urb->transfer_flags = URB_ZERO_PACKET;
533
534 BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
535
536 _urb->priv = skb;
537 return __tx_submit(husb, _urb);
538}
539
540#ifdef CONFIG_BT_HCIUSB_SCO
541static inline int hci_usb_send_isoc(struct hci_usb *husb, struct sk_buff *skb)
542{
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700543 struct _urb *_urb = __get_completed(husb, bt_cb(skb)->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 struct urb *urb;
545
546 if (!_urb) {
547 _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC);
548 if (!_urb)
549 return -ENOMEM;
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700550 _urb->type = bt_cb(skb)->pkt_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 }
552
553 BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len);
554
555 urb = &_urb->urb;
556
557 urb->context = husb;
558 urb->dev = husb->udev;
559 urb->pipe = usb_sndisocpipe(husb->udev, husb->isoc_out_ep->desc.bEndpointAddress);
560 urb->complete = hci_usb_tx_complete;
561 urb->transfer_flags = URB_ISO_ASAP;
562
563 urb->interval = husb->isoc_out_ep->desc.bInterval;
564
565 urb->transfer_buffer = skb->data;
566 urb->transfer_buffer_length = skb->len;
567
568 __fill_isoc_desc(urb, skb->len, le16_to_cpu(husb->isoc_out_ep->desc.wMaxPacketSize));
569
570 _urb->priv = skb;
571 return __tx_submit(husb, _urb);
572}
573#endif
574
575static void hci_usb_tx_process(struct hci_usb *husb)
576{
577 struct sk_buff_head *q;
578 struct sk_buff *skb;
579
580 BT_DBG("%s", husb->hdev->name);
581
582 do {
583 clear_bit(HCI_USB_TX_WAKEUP, &husb->state);
584
585 /* Process command queue */
586 q = __transmit_q(husb, HCI_COMMAND_PKT);
587 if (!atomic_read(__pending_tx(husb, HCI_COMMAND_PKT)) &&
588 (skb = skb_dequeue(q))) {
589 if (hci_usb_send_ctrl(husb, skb) < 0)
590 skb_queue_head(q, skb);
591 }
592
593#ifdef CONFIG_BT_HCIUSB_SCO
594 /* Process SCO queue */
595 q = __transmit_q(husb, HCI_SCODATA_PKT);
596 if (atomic_read(__pending_tx(husb, HCI_SCODATA_PKT)) < HCI_MAX_ISOC_TX &&
597 (skb = skb_dequeue(q))) {
598 if (hci_usb_send_isoc(husb, skb) < 0)
599 skb_queue_head(q, skb);
600 }
601#endif
602
603 /* Process ACL queue */
604 q = __transmit_q(husb, HCI_ACLDATA_PKT);
605 while (atomic_read(__pending_tx(husb, HCI_ACLDATA_PKT)) < HCI_MAX_BULK_TX &&
606 (skb = skb_dequeue(q))) {
607 if (hci_usb_send_bulk(husb, skb) < 0) {
608 skb_queue_head(q, skb);
609 break;
610 }
611 }
612 } while(test_bit(HCI_USB_TX_WAKEUP, &husb->state));
613}
614
615static inline void hci_usb_tx_wakeup(struct hci_usb *husb)
616{
617 /* Serialize TX queue processing to avoid data reordering */
618 if (!test_and_set_bit(HCI_USB_TX_PROCESS, &husb->state)) {
619 hci_usb_tx_process(husb);
620 clear_bit(HCI_USB_TX_PROCESS, &husb->state);
621 } else
622 set_bit(HCI_USB_TX_WAKEUP, &husb->state);
623}
624
625/* Send frames from HCI layer */
626static int hci_usb_send_frame(struct sk_buff *skb)
627{
628 struct hci_dev *hdev = (struct hci_dev *) skb->dev;
629 struct hci_usb *husb;
630
631 if (!hdev) {
632 BT_ERR("frame for uknown device (hdev=NULL)");
633 return -ENODEV;
634 }
635
636 if (!test_bit(HCI_RUNNING, &hdev->flags))
637 return -EBUSY;
638
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700639 BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641 husb = (struct hci_usb *) hdev->driver_data;
642
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700643 switch (bt_cb(skb)->pkt_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 case HCI_COMMAND_PKT:
645 hdev->stat.cmd_tx++;
646 break;
647
648 case HCI_ACLDATA_PKT:
649 hdev->stat.acl_tx++;
650 break;
651
652#ifdef CONFIG_BT_HCIUSB_SCO
653 case HCI_SCODATA_PKT:
654 hdev->stat.sco_tx++;
655 break;
656#endif
657
658 default:
659 kfree_skb(skb);
660 return 0;
661 }
662
663 read_lock(&husb->completion_lock);
664
Marcel Holtmann0d48d932005-08-09 20:30:28 -0700665 skb_queue_tail(__transmit_q(husb, bt_cb(skb)->pkt_type), skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 hci_usb_tx_wakeup(husb);
667
668 read_unlock(&husb->completion_lock);
669 return 0;
670}
671
David Howells7d12e782006-10-05 14:55:46 +0100672static void hci_usb_rx_complete(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673{
674 struct _urb *_urb = container_of(urb, struct _urb, urb);
675 struct hci_usb *husb = (void *) urb->context;
676 struct hci_dev *hdev = husb->hdev;
677 int err, count = urb->actual_length;
678
679 BT_DBG("%s urb %p type %d status %d count %d flags %x", hdev->name, urb,
680 _urb->type, urb->status, count, urb->transfer_flags);
681
682 read_lock(&husb->completion_lock);
683
684 if (!test_bit(HCI_RUNNING, &hdev->flags))
685 goto unlock;
686
687 if (urb->status || !count)
688 goto resubmit;
689
690 if (_urb->type == HCI_SCODATA_PKT) {
691#ifdef CONFIG_BT_HCIUSB_SCO
692 int i;
693 for (i=0; i < urb->number_of_packets; i++) {
694 BT_DBG("desc %d status %d offset %d len %d", i,
695 urb->iso_frame_desc[i].status,
696 urb->iso_frame_desc[i].offset,
697 urb->iso_frame_desc[i].actual_length);
698
Marcel Holtmann26a4a062007-09-09 08:39:27 +0200699 if (!urb->iso_frame_desc[i].status) {
700 husb->hdev->stat.byte_rx += urb->iso_frame_desc[i].actual_length;
Marcel Holtmannbabf4d42007-07-11 06:42:35 +0200701 hci_recv_fragment(husb->hdev, _urb->type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 urb->transfer_buffer + urb->iso_frame_desc[i].offset,
703 urb->iso_frame_desc[i].actual_length);
Marcel Holtmann26a4a062007-09-09 08:39:27 +0200704 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 }
706#else
707 ;
708#endif
709 } else {
Marcel Holtmann26a4a062007-09-09 08:39:27 +0200710 husb->hdev->stat.byte_rx += count;
Marcel Holtmannbabf4d42007-07-11 06:42:35 +0200711 err = hci_recv_fragment(husb->hdev, _urb->type, urb->transfer_buffer, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 if (err < 0) {
713 BT_ERR("%s corrupted packet: type %d count %d",
714 husb->hdev->name, _urb->type, count);
715 hdev->stat.err_rx++;
716 }
717 }
718
719resubmit:
720 urb->dev = husb->udev;
721 err = usb_submit_urb(urb, GFP_ATOMIC);
722 BT_DBG("%s urb %p type %d resubmit status %d", hdev->name, urb,
723 _urb->type, err);
724
725unlock:
726 read_unlock(&husb->completion_lock);
727}
728
David Howells7d12e782006-10-05 14:55:46 +0100729static void hci_usb_tx_complete(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
731 struct _urb *_urb = container_of(urb, struct _urb, urb);
732 struct hci_usb *husb = (void *) urb->context;
733 struct hci_dev *hdev = husb->hdev;
734
735 BT_DBG("%s urb %p status %d flags %x", hdev->name, urb,
736 urb->status, urb->transfer_flags);
737
738 atomic_dec(__pending_tx(husb, _urb->type));
739
740 urb->transfer_buffer = NULL;
741 kfree_skb((struct sk_buff *) _urb->priv);
742
743 if (!test_bit(HCI_RUNNING, &hdev->flags))
744 return;
745
746 if (!urb->status)
747 hdev->stat.byte_tx += urb->transfer_buffer_length;
748 else
749 hdev->stat.err_tx++;
750
751 read_lock(&husb->completion_lock);
752
753 _urb_unlink(_urb);
754 _urb_queue_tail(__completed_q(husb, _urb->type), _urb);
755
756 hci_usb_tx_wakeup(husb);
757
758 read_unlock(&husb->completion_lock);
759}
760
761static void hci_usb_destruct(struct hci_dev *hdev)
762{
763 struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
764
765 BT_DBG("%s", hdev->name);
766
767 kfree(husb);
768}
769
770static void hci_usb_notify(struct hci_dev *hdev, unsigned int evt)
771{
772 BT_DBG("%s evt %d", hdev->name, evt);
773}
774
775static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
776{
777 struct usb_device *udev = interface_to_usbdev(intf);
778 struct usb_host_endpoint *bulk_out_ep = NULL;
779 struct usb_host_endpoint *bulk_in_ep = NULL;
780 struct usb_host_endpoint *intr_in_ep = NULL;
781 struct usb_host_endpoint *ep;
782 struct usb_host_interface *uif;
783 struct usb_interface *isoc_iface;
784 struct hci_usb *husb;
785 struct hci_dev *hdev;
786 int i, e, size, isoc_ifnum, isoc_alts;
787
788 BT_DBG("udev %p intf %p", udev, intf);
789
790 if (!id->driver_info) {
791 const struct usb_device_id *match;
792 match = usb_match_id(intf, blacklist_ids);
793 if (match)
794 id = match;
795 }
796
797 if (ignore || id->driver_info & HCI_IGNORE)
798 return -ENODEV;
799
Marcel Holtmann7ef934b2005-11-08 09:57:05 -0800800 if (ignore_dga && id->driver_info & HCI_DIGIANSWER)
801 return -ENODEV;
802
Marcel Holtmann0915e882005-09-13 01:32:37 +0200803 if (ignore_csr && id->driver_info & HCI_CSR)
804 return -ENODEV;
805
806 if (ignore_sniffer && id->driver_info & HCI_SNIFFER)
807 return -ENODEV;
808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
810 return -ENODEV;
811
812 /* Find endpoints that we need */
813 uif = intf->cur_altsetting;
814 for (e = 0; e < uif->desc.bNumEndpoints; e++) {
815 ep = &uif->endpoint[e];
816
817 switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
818 case USB_ENDPOINT_XFER_INT:
819 if (ep->desc.bEndpointAddress & USB_DIR_IN)
820 intr_in_ep = ep;
821 break;
822
823 case USB_ENDPOINT_XFER_BULK:
824 if (ep->desc.bEndpointAddress & USB_DIR_IN)
825 bulk_in_ep = ep;
826 else
827 bulk_out_ep = ep;
828 break;
829 }
830 }
831
832 if (!bulk_in_ep || !bulk_out_ep || !intr_in_ep) {
833 BT_DBG("Bulk endpoints not found");
834 goto done;
835 }
836
Deepak Saxena089b1db2005-11-07 01:01:26 -0800837 if (!(husb = kzalloc(sizeof(struct hci_usb), GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 BT_ERR("Can't allocate: control structure");
839 goto done;
840 }
841
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 husb->udev = udev;
843 husb->bulk_out_ep = bulk_out_ep;
844 husb->bulk_in_ep = bulk_in_ep;
845 husb->intr_in_ep = intr_in_ep;
846
847 if (id->driver_info & HCI_DIGIANSWER)
848 husb->ctrl_req = USB_TYPE_VENDOR;
849 else
850 husb->ctrl_req = USB_TYPE_CLASS;
851
852 /* Find isochronous endpoints that we can use */
853 size = 0;
854 isoc_iface = NULL;
855 isoc_alts = 0;
856 isoc_ifnum = 1;
857
858#ifdef CONFIG_BT_HCIUSB_SCO
859 if (isoc && !(id->driver_info & (HCI_BROKEN_ISOC | HCI_SNIFFER)))
860 isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
861
862 if (isoc_iface) {
863 int a;
864 struct usb_host_endpoint *isoc_out_ep = NULL;
865 struct usb_host_endpoint *isoc_in_ep = NULL;
866
867 for (a = 0; a < isoc_iface->num_altsetting; a++) {
868 uif = &isoc_iface->altsetting[a];
869 for (e = 0; e < uif->desc.bNumEndpoints; e++) {
870 ep = &uif->endpoint[e];
871
872 switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
873 case USB_ENDPOINT_XFER_ISOC:
874 if (le16_to_cpu(ep->desc.wMaxPacketSize) < size ||
875 uif->desc.bAlternateSetting != isoc)
876 break;
877 size = le16_to_cpu(ep->desc.wMaxPacketSize);
878
879 isoc_alts = uif->desc.bAlternateSetting;
880
881 if (ep->desc.bEndpointAddress & USB_DIR_IN)
882 isoc_in_ep = ep;
883 else
884 isoc_out_ep = ep;
885 break;
886 }
887 }
888 }
889
890 if (!isoc_in_ep || !isoc_out_ep)
891 BT_DBG("Isoc endpoints not found");
892 else {
893 BT_DBG("isoc ifnum %d alts %d", isoc_ifnum, isoc_alts);
894 if (usb_driver_claim_interface(&hci_usb_driver, isoc_iface, husb) != 0)
895 BT_ERR("Can't claim isoc interface");
896 else if (usb_set_interface(udev, isoc_ifnum, isoc_alts)) {
897 BT_ERR("Can't set isoc interface settings");
898 husb->isoc_iface = isoc_iface;
899 usb_driver_release_interface(&hci_usb_driver, isoc_iface);
900 husb->isoc_iface = NULL;
901 } else {
902 husb->isoc_iface = isoc_iface;
903 husb->isoc_in_ep = isoc_in_ep;
904 husb->isoc_out_ep = isoc_out_ep;
905 }
906 }
907 }
908#endif
909
910 rwlock_init(&husb->completion_lock);
911
912 for (i = 0; i < 4; i++) {
913 skb_queue_head_init(&husb->transmit_q[i]);
914 _urb_queue_init(&husb->pending_q[i]);
915 _urb_queue_init(&husb->completed_q[i]);
916 }
917
918 /* Initialize and register HCI device */
919 hdev = hci_alloc_dev();
920 if (!hdev) {
921 BT_ERR("Can't allocate HCI device");
922 goto probe_error;
923 }
924
925 husb->hdev = hdev;
926
927 hdev->type = HCI_USB;
928 hdev->driver_data = husb;
929 SET_HCIDEV_DEV(hdev, &intf->dev);
930
931 hdev->open = hci_usb_open;
932 hdev->close = hci_usb_close;
933 hdev->flush = hci_usb_flush;
934 hdev->send = hci_usb_send_frame;
935 hdev->destruct = hci_usb_destruct;
936 hdev->notify = hci_usb_notify;
937
938 hdev->owner = THIS_MODULE;
939
940 if (reset || id->driver_info & HCI_RESET)
941 set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
942
Marcel Holtmann520ca782006-07-14 16:01:52 +0200943 if (force_scofix || id->driver_info & HCI_WRONG_SCO_MTU) {
944 if (!disable_scofix)
945 set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
946 }
Marcel Holtmannda1f5192006-07-03 10:02:29 +0200947
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 if (id->driver_info & HCI_SNIFFER) {
949 if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
950 set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
951 }
952
953 if (id->driver_info & HCI_BCM92035) {
954 unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
955 struct sk_buff *skb;
956
957 skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
958 if (skb) {
959 memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
960 skb_queue_tail(&hdev->driver_init, skb);
961 }
962 }
963
964 if (hci_register_dev(hdev) < 0) {
965 BT_ERR("Can't register HCI device");
966 hci_free_dev(hdev);
967 goto probe_error;
968 }
969
970 usb_set_intfdata(intf, husb);
971 return 0;
972
973probe_error:
974 if (husb->isoc_iface)
975 usb_driver_release_interface(&hci_usb_driver, husb->isoc_iface);
976 kfree(husb);
977
978done:
979 return -EIO;
980}
981
982static void hci_usb_disconnect(struct usb_interface *intf)
983{
984 struct hci_usb *husb = usb_get_intfdata(intf);
985 struct hci_dev *hdev;
986
987 if (!husb || intf == husb->isoc_iface)
988 return;
989
990 usb_set_intfdata(intf, NULL);
991 hdev = husb->hdev;
992
993 BT_DBG("%s", hdev->name);
994
995 hci_usb_close(hdev);
996
997 if (husb->isoc_iface)
998 usb_driver_release_interface(&hci_usb_driver, husb->isoc_iface);
999
1000 if (hci_unregister_dev(hdev) < 0)
1001 BT_ERR("Can't unregister HCI device %s", hdev->name);
1002
1003 hci_free_dev(hdev);
1004}
1005
Marcel Holtmanndcdcf632006-07-03 10:02:24 +02001006static int hci_usb_suspend(struct usb_interface *intf, pm_message_t message)
1007{
1008 struct hci_usb *husb = usb_get_intfdata(intf);
1009 struct list_head killed;
1010 unsigned long flags;
1011 int i;
1012
1013 if (!husb || intf == husb->isoc_iface)
1014 return 0;
1015
1016 hci_suspend_dev(husb->hdev);
1017
1018 INIT_LIST_HEAD(&killed);
1019
1020 for (i = 0; i < 4; i++) {
1021 struct _urb_queue *q = &husb->pending_q[i];
1022 struct _urb *_urb, *_tmp;
1023
1024 while ((_urb = _urb_dequeue(q))) {
1025 /* reset queue since _urb_dequeue sets it to NULL */
1026 _urb->queue = q;
1027 usb_kill_urb(&_urb->urb);
1028 list_add(&_urb->list, &killed);
1029 }
1030
1031 spin_lock_irqsave(&q->lock, flags);
1032
1033 list_for_each_entry_safe(_urb, _tmp, &killed, list) {
1034 list_move_tail(&_urb->list, &q->head);
1035 }
1036
1037 spin_unlock_irqrestore(&q->lock, flags);
1038 }
1039
1040 return 0;
1041}
1042
1043static int hci_usb_resume(struct usb_interface *intf)
1044{
1045 struct hci_usb *husb = usb_get_intfdata(intf);
1046 unsigned long flags;
1047 int i, err = 0;
1048
1049 if (!husb || intf == husb->isoc_iface)
1050 return 0;
1051
1052 for (i = 0; i < 4; i++) {
1053 struct _urb_queue *q = &husb->pending_q[i];
1054 struct _urb *_urb;
1055
1056 spin_lock_irqsave(&q->lock, flags);
1057
1058 list_for_each_entry(_urb, &q->head, list) {
1059 err = usb_submit_urb(&_urb->urb, GFP_ATOMIC);
1060 if (err)
1061 break;
1062 }
1063
1064 spin_unlock_irqrestore(&q->lock, flags);
1065
1066 if (err)
1067 return -EIO;
1068 }
1069
1070 hci_resume_dev(husb->hdev);
1071
1072 return 0;
1073}
1074
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075static struct usb_driver hci_usb_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 .name = "hci_usb",
1077 .probe = hci_usb_probe,
1078 .disconnect = hci_usb_disconnect,
Marcel Holtmanndcdcf632006-07-03 10:02:24 +02001079 .suspend = hci_usb_suspend,
1080 .resume = hci_usb_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 .id_table = bluetooth_ids,
1082};
1083
1084static int __init hci_usb_init(void)
1085{
1086 int err;
1087
1088 BT_INFO("HCI USB driver ver %s", VERSION);
1089
1090 if ((err = usb_register(&hci_usb_driver)) < 0)
1091 BT_ERR("Failed to register HCI USB driver");
1092
1093 return err;
1094}
1095
1096static void __exit hci_usb_exit(void)
1097{
1098 usb_deregister(&hci_usb_driver);
1099}
1100
1101module_init(hci_usb_init);
1102module_exit(hci_usb_exit);
1103
1104module_param(ignore, bool, 0644);
1105MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
1106
Marcel Holtmann7ef934b2005-11-08 09:57:05 -08001107module_param(ignore_dga, bool, 0644);
1108MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
1109
Marcel Holtmann0915e882005-09-13 01:32:37 +02001110module_param(ignore_csr, bool, 0644);
1111MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
1112
1113module_param(ignore_sniffer, bool, 0644);
1114MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
1115
Marcel Holtmann520ca782006-07-14 16:01:52 +02001116module_param(disable_scofix, bool, 0644);
1117MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
1118
1119module_param(force_scofix, bool, 0644);
1120MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size");
1121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122module_param(reset, bool, 0644);
1123MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
1124
1125#ifdef CONFIG_BT_HCIUSB_SCO
1126module_param(isoc, int, 0644);
1127MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support");
1128#endif
1129
1130MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
1131MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION);
1132MODULE_VERSION(VERSION);
1133MODULE_LICENSE("GPL");