aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/btusb.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2007-10-20 08:12:34 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-22 05:59:46 -0400
commit5e23b923da03de7e41f00f5664ae22c4f7dcd2a3 (patch)
tree53caf3acacebb88d776f5086a8b084de6d528d22 /drivers/bluetooth/btusb.c
parentddbaf13e3609442b64abb931ac21527772d87980 (diff)
[Bluetooth] Add generic driver for Bluetooth USB devices
This patch adds a new generic driver for Bluetooth USB devices. This driver is still experimental at this point, but it is cleaner and easier to maintain than the current Bluetooth USB driver. It is a much better starting point for power management improvements. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r--drivers/bluetooth/btusb.c564
1 files changed, 564 insertions, 0 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
new file mode 100644
index 000000000000..12e108914f19
--- /dev/null
+++ b/drivers/bluetooth/btusb.c
@@ -0,0 +1,564 @@
1/*
2 *
3 * Generic Bluetooth USB driver
4 *
5 * Copyright (C) 2005-2007 Marcel Holtmann <marcel@holtmann.org>
6 *
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 as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/slab.h>
28#include <linux/types.h>
29#include <linux/sched.h>
30#include <linux/errno.h>
31#include <linux/skbuff.h>
32
33#include <linux/usb.h>
34
35#include <net/bluetooth/bluetooth.h>
36#include <net/bluetooth/hci_core.h>
37
38//#define CONFIG_BT_HCIBTUSB_DEBUG
39#ifndef CONFIG_BT_HCIBTUSB_DEBUG
40#undef BT_DBG
41#define BT_DBG(D...)
42#endif
43
44#define VERSION "0.1"
45
46static struct usb_device_id btusb_table[] = {
47 /* Generic Bluetooth USB device */
48 { USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
49
50 { } /* Terminating entry */
51};
52
53MODULE_DEVICE_TABLE(usb, btusb_table);
54
55static struct usb_device_id blacklist_table[] = {
56 { } /* Terminating entry */
57};
58
59#define BTUSB_INTR_RUNNING 0
60#define BTUSB_BULK_RUNNING 1
61
62struct btusb_data {
63 struct hci_dev *hdev;
64 struct usb_device *udev;
65
66 spinlock_t lock;
67
68 unsigned long flags;
69
70 struct work_struct work;
71
72 struct usb_anchor tx_anchor;
73 struct usb_anchor intr_anchor;
74 struct usb_anchor bulk_anchor;
75
76 struct usb_endpoint_descriptor *intr_ep;
77 struct usb_endpoint_descriptor *bulk_tx_ep;
78 struct usb_endpoint_descriptor *bulk_rx_ep;
79};
80
81static void btusb_intr_complete(struct urb *urb)
82{
83 struct hci_dev *hdev = urb->context;
84 struct btusb_data *data = hdev->driver_data;
85 int err;
86
87 BT_DBG("%s urb %p status %d count %d", hdev->name,
88 urb, urb->status, urb->actual_length);
89
90 if (!test_bit(HCI_RUNNING, &hdev->flags))
91 return;
92
93 if (urb->status == 0) {
94 if (hci_recv_fragment(hdev, HCI_EVENT_PKT,
95 urb->transfer_buffer,
96 urb->actual_length) < 0) {
97 BT_ERR("%s corrupted event packet", hdev->name);
98 hdev->stat.err_rx++;
99 }
100 }
101
102 if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
103 return;
104
105 usb_anchor_urb(urb, &data->intr_anchor);
106
107 err = usb_submit_urb(urb, GFP_ATOMIC);
108 if (err < 0) {
109 BT_ERR("%s urb %p failed to resubmit (%d)",
110 hdev->name, urb, -err);
111 usb_unanchor_urb(urb);
112 }
113}
114
115static inline int btusb_submit_intr_urb(struct hci_dev *hdev)
116{
117 struct btusb_data *data = hdev->driver_data;
118 struct urb *urb;
119 unsigned char *buf;
120 unsigned int pipe;
121 int err, size;
122
123 BT_DBG("%s", hdev->name);
124
125 urb = usb_alloc_urb(0, GFP_ATOMIC);
126 if (!urb)
127 return -ENOMEM;
128
129 size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
130
131 buf = kmalloc(size, GFP_ATOMIC);
132 if (!buf) {
133 usb_free_urb(urb);
134 return -ENOMEM;
135 }
136
137 pipe = usb_rcvintpipe(data->udev, data->intr_ep->bEndpointAddress);
138
139 usb_fill_int_urb(urb, data->udev, pipe, buf, size,
140 btusb_intr_complete, hdev,
141 data->intr_ep->bInterval);
142
143 urb->transfer_flags |= URB_FREE_BUFFER;
144
145 usb_anchor_urb(urb, &data->intr_anchor);
146
147 err = usb_submit_urb(urb, GFP_ATOMIC);
148 if (err < 0) {
149 BT_ERR("%s urb %p submission failed (%d)",
150 hdev->name, urb, -err);
151 usb_unanchor_urb(urb);
152 kfree(buf);
153 }
154
155 usb_free_urb(urb);
156
157 return err;
158}
159
160static void btusb_bulk_complete(struct urb *urb)
161{
162 struct hci_dev *hdev = urb->context;
163 struct btusb_data *data = hdev->driver_data;
164 int err;
165
166 BT_DBG("%s urb %p status %d count %d", hdev->name,
167 urb, urb->status, urb->actual_length);
168
169 if (!test_bit(HCI_RUNNING, &hdev->flags))
170 return;
171
172 if (urb->status == 0) {
173 if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT,
174 urb->transfer_buffer,
175 urb->actual_length) < 0) {
176 BT_ERR("%s corrupted ACL packet", hdev->name);
177 hdev->stat.err_rx++;
178 }
179 }
180
181 if (!test_bit(BTUSB_BULK_RUNNING, &data->flags))
182 return;
183
184 usb_anchor_urb(urb, &data->bulk_anchor);
185
186 err = usb_submit_urb(urb, GFP_ATOMIC);
187 if (err < 0) {
188 BT_ERR("%s urb %p failed to resubmit (%d)",
189 hdev->name, urb, -err);
190 usb_unanchor_urb(urb);
191 }
192}
193
194static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
195{
196 struct btusb_data *data = hdev->driver_data;
197 struct urb *urb;
198 unsigned char *buf;
199 unsigned int pipe;
200 int err, size;
201
202 BT_DBG("%s", hdev->name);
203
204 urb = usb_alloc_urb(0, GFP_KERNEL);
205 if (!urb)
206 return -ENOMEM;
207
208 size = le16_to_cpu(data->bulk_rx_ep->wMaxPacketSize);
209
210 buf = kmalloc(size, GFP_KERNEL);
211 if (!buf) {
212 usb_free_urb(urb);
213 return -ENOMEM;
214 }
215
216 pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress);
217
218 usb_fill_bulk_urb(urb, data->udev, pipe,
219 buf, size, btusb_bulk_complete, hdev);
220
221 urb->transfer_flags |= URB_FREE_BUFFER;
222
223 usb_anchor_urb(urb, &data->bulk_anchor);
224
225 err = usb_submit_urb(urb, GFP_KERNEL);
226 if (err < 0) {
227 BT_ERR("%s urb %p submission failed (%d)",
228 hdev->name, urb, -err);
229 usb_unanchor_urb(urb);
230 kfree(buf);
231 }
232
233 usb_free_urb(urb);
234
235 return err;
236}
237
238static void btusb_tx_complete(struct urb *urb)
239{
240 struct sk_buff *skb = urb->context;
241 struct hci_dev *hdev = (struct hci_dev *) skb->dev;
242
243 BT_DBG("%s urb %p status %d count %d", hdev->name,
244 urb, urb->status, urb->actual_length);
245
246 if (!test_bit(HCI_RUNNING, &hdev->flags))
247 goto done;
248
249 if (!urb->status)
250 hdev->stat.byte_tx += urb->transfer_buffer_length;
251 else
252 hdev->stat.err_tx++;
253
254done:
255 kfree(urb->setup_packet);
256
257 kfree_skb(skb);
258}
259
260static int btusb_open(struct hci_dev *hdev)
261{
262 struct btusb_data *data = hdev->driver_data;
263 int err;
264
265 BT_DBG("%s", hdev->name);
266
267 if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
268 return 0;
269
270 if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
271 return 0;
272
273 err = btusb_submit_intr_urb(hdev);
274 if (err < 0) {
275 clear_bit(BTUSB_INTR_RUNNING, &hdev->flags);
276 clear_bit(HCI_RUNNING, &hdev->flags);
277 }
278
279 return err;
280}
281
282static int btusb_close(struct hci_dev *hdev)
283{
284 struct btusb_data *data = hdev->driver_data;
285
286 BT_DBG("%s", hdev->name);
287
288 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
289 return 0;
290
291 clear_bit(BTUSB_BULK_RUNNING, &data->flags);
292 usb_kill_anchored_urbs(&data->bulk_anchor);
293
294 clear_bit(BTUSB_INTR_RUNNING, &data->flags);
295 usb_kill_anchored_urbs(&data->intr_anchor);
296
297 return 0;
298}
299
300static int btusb_flush(struct hci_dev *hdev)
301{
302 struct btusb_data *data = hdev->driver_data;
303
304 BT_DBG("%s", hdev->name);
305
306 usb_kill_anchored_urbs(&data->tx_anchor);
307
308 return 0;
309}
310
311static int btusb_send_frame(struct sk_buff *skb)
312{
313 struct hci_dev *hdev = (struct hci_dev *) skb->dev;
314 struct btusb_data *data = hdev->driver_data;
315 struct usb_ctrlrequest *dr;
316 struct urb *urb;
317 unsigned int pipe;
318 int err;
319
320 BT_DBG("%s", hdev->name);
321
322 if (!test_bit(HCI_RUNNING, &hdev->flags))
323 return -EBUSY;
324
325 switch (bt_cb(skb)->pkt_type) {
326 case HCI_COMMAND_PKT:
327 urb = usb_alloc_urb(0, GFP_ATOMIC);
328 if (!urb)
329 return -ENOMEM;
330
331 dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
332 if (!dr) {
333 usb_free_urb(urb);
334 return -ENOMEM;
335 }
336
337 dr->bRequestType = USB_TYPE_CLASS;
338 dr->bRequest = 0;
339 dr->wIndex = 0;
340 dr->wValue = 0;
341 dr->wLength = __cpu_to_le16(skb->len);
342
343 pipe = usb_sndctrlpipe(data->udev, 0x00);
344
345 usb_fill_control_urb(urb, data->udev, pipe, (void *) dr,
346 skb->data, skb->len, btusb_tx_complete, skb);
347
348 hdev->stat.cmd_tx++;
349 break;
350
351 case HCI_ACLDATA_PKT:
352 urb = usb_alloc_urb(0, GFP_ATOMIC);
353 if (!urb)
354 return -ENOMEM;
355
356 pipe = usb_sndbulkpipe(data->udev,
357 data->bulk_tx_ep->bEndpointAddress);
358
359 usb_fill_bulk_urb(urb, data->udev, pipe,
360 skb->data, skb->len, btusb_tx_complete, skb);
361
362 hdev->stat.acl_tx++;
363 break;
364
365 case HCI_SCODATA_PKT:
366 hdev->stat.sco_tx++;
367 kfree_skb(skb);
368 return 0;
369
370 default:
371 return -EILSEQ;
372 }
373
374 usb_anchor_urb(urb, &data->tx_anchor);
375
376 err = usb_submit_urb(urb, GFP_ATOMIC);
377 if (err < 0) {
378 BT_ERR("%s urb %p submission failed", hdev->name, urb);
379 kfree(urb->setup_packet);
380 usb_unanchor_urb(urb);
381 }
382
383 usb_free_urb(urb);
384
385 return err;
386}
387
388static void btusb_destruct(struct hci_dev *hdev)
389{
390 struct btusb_data *data = hdev->driver_data;
391
392 BT_DBG("%s", hdev->name);
393
394 kfree(data);
395}
396
397static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
398{
399 struct btusb_data *data = hdev->driver_data;
400
401 BT_DBG("%s evt %d", hdev->name, evt);
402
403 if (evt == HCI_NOTIFY_CONN_ADD || evt == HCI_NOTIFY_CONN_DEL)
404 schedule_work(&data->work);
405}
406
407static void btusb_work(struct work_struct *work)
408{
409 struct btusb_data *data = container_of(work, struct btusb_data, work);
410 struct hci_dev *hdev = data->hdev;
411
412 if (hdev->conn_hash.acl_num == 0) {
413 clear_bit(BTUSB_BULK_RUNNING, &data->flags);
414 usb_kill_anchored_urbs(&data->bulk_anchor);
415 return;
416 }
417
418 if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
419 if (btusb_submit_bulk_urb(hdev) < 0)
420 clear_bit(BTUSB_BULK_RUNNING, &data->flags);
421 else
422 btusb_submit_bulk_urb(hdev);
423 }
424}
425
426static int btusb_probe(struct usb_interface *intf,
427 const struct usb_device_id *id)
428{
429 struct usb_endpoint_descriptor *ep_desc;
430 struct btusb_data *data;
431 struct hci_dev *hdev;
432 int i, err;
433
434 BT_DBG("intf %p id %p", intf, id);
435
436 if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
437 return -ENODEV;
438
439 if (!id->driver_info) {
440 const struct usb_device_id *match;
441 match = usb_match_id(intf, blacklist_table);
442 if (match)
443 id = match;
444 }
445
446 data = kzalloc(sizeof(*data), GFP_KERNEL);
447 if (!data)
448 return -ENOMEM;
449
450 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
451 ep_desc = &intf->cur_altsetting->endpoint[i].desc;
452
453 if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) {
454 data->intr_ep = ep_desc;
455 continue;
456 }
457
458 if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
459 data->bulk_tx_ep = ep_desc;
460 continue;
461 }
462
463 if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
464 data->bulk_rx_ep = ep_desc;
465 continue;
466 }
467 }
468
469 if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
470 kfree(data);
471 return -ENODEV;
472 }
473
474 data->udev = interface_to_usbdev(intf);
475
476 spin_lock_init(&data->lock);
477
478 INIT_WORK(&data->work, btusb_work);
479
480 init_usb_anchor(&data->tx_anchor);
481 init_usb_anchor(&data->intr_anchor);
482 init_usb_anchor(&data->bulk_anchor);
483
484 hdev = hci_alloc_dev();
485 if (!hdev) {
486 kfree(data);
487 return -ENOMEM;
488 }
489
490 hdev->type = HCI_USB;
491 hdev->driver_data = data;
492
493 data->hdev = hdev;
494
495 SET_HCIDEV_DEV(hdev, &intf->dev);
496
497 hdev->open = btusb_open;
498 hdev->close = btusb_close;
499 hdev->flush = btusb_flush;
500 hdev->send = btusb_send_frame;
501 hdev->destruct = btusb_destruct;
502 hdev->notify = btusb_notify;
503
504 hdev->owner = THIS_MODULE;
505
506 set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
507
508 err = hci_register_dev(hdev);
509 if (err < 0) {
510 hci_free_dev(hdev);
511 kfree(data);
512 return err;
513 }
514
515 usb_set_intfdata(intf, data);
516
517 return 0;
518}
519
520static void btusb_disconnect(struct usb_interface *intf)
521{
522 struct btusb_data *data = usb_get_intfdata(intf);
523 struct hci_dev *hdev;
524
525 BT_DBG("intf %p", intf);
526
527 if (!data)
528 return;
529
530 hdev = data->hdev;
531
532 usb_set_intfdata(intf, NULL);
533
534 hci_unregister_dev(hdev);
535
536 hci_free_dev(hdev);
537}
538
539static struct usb_driver btusb_driver = {
540 .name = "btusb",
541 .probe = btusb_probe,
542 .disconnect = btusb_disconnect,
543 .id_table = btusb_table,
544};
545
546static int __init btusb_init(void)
547{
548 BT_INFO("Generic Bluetooth USB driver ver %s", VERSION);
549
550 return usb_register(&btusb_driver);
551}
552
553static void __exit btusb_exit(void)
554{
555 usb_deregister(&btusb_driver);
556}
557
558module_init(btusb_init);
559module_exit(btusb_exit);
560
561MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
562MODULE_DESCRIPTION("Generic Bluetooth USB driver ver " VERSION);
563MODULE_VERSION(VERSION);
564MODULE_LICENSE("GPL");