diff options
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r-- | drivers/bluetooth/btusb.c | 302 |
1 files changed, 286 insertions, 16 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 95ae9ba5661e..29ae99817c60 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Generic Bluetooth USB driver | 3 | * Generic Bluetooth USB driver |
4 | * | 4 | * |
5 | * Copyright (C) 2005-2007 Marcel Holtmann <marcel@holtmann.org> | 5 | * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org> |
6 | * | 6 | * |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -41,7 +41,7 @@ | |||
41 | #define BT_DBG(D...) | 41 | #define BT_DBG(D...) |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #define VERSION "0.2" | 44 | #define VERSION "0.3" |
45 | 45 | ||
46 | static int ignore_dga; | 46 | static int ignore_dga; |
47 | static int ignore_csr; | 47 | static int ignore_csr; |
@@ -104,6 +104,9 @@ static struct usb_device_id blacklist_table[] = { | |||
104 | /* Broadcom BCM2046 */ | 104 | /* Broadcom BCM2046 */ |
105 | { USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET }, | 105 | { USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET }, |
106 | 106 | ||
107 | /* Apple MacBook Pro with Broadcom chip */ | ||
108 | { USB_DEVICE(0x05ac, 0x820f), .driver_info = BTUSB_RESET }, | ||
109 | |||
107 | /* IBM/Lenovo ThinkPad with Broadcom chip */ | 110 | /* IBM/Lenovo ThinkPad with Broadcom chip */ |
108 | { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, | 111 | { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, |
109 | { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, | 112 | { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, |
@@ -160,12 +163,17 @@ static struct usb_device_id blacklist_table[] = { | |||
160 | { } /* Terminating entry */ | 163 | { } /* Terminating entry */ |
161 | }; | 164 | }; |
162 | 165 | ||
166 | #define BTUSB_MAX_ISOC_FRAMES 10 | ||
167 | |||
163 | #define BTUSB_INTR_RUNNING 0 | 168 | #define BTUSB_INTR_RUNNING 0 |
164 | #define BTUSB_BULK_RUNNING 1 | 169 | #define BTUSB_BULK_RUNNING 1 |
170 | #define BTUSB_ISOC_RUNNING 2 | ||
165 | 171 | ||
166 | struct btusb_data { | 172 | struct btusb_data { |
167 | struct hci_dev *hdev; | 173 | struct hci_dev *hdev; |
168 | struct usb_device *udev; | 174 | struct usb_device *udev; |
175 | struct usb_interface *intf; | ||
176 | struct usb_interface *isoc; | ||
169 | 177 | ||
170 | spinlock_t lock; | 178 | spinlock_t lock; |
171 | 179 | ||
@@ -176,10 +184,15 @@ struct btusb_data { | |||
176 | struct usb_anchor tx_anchor; | 184 | struct usb_anchor tx_anchor; |
177 | struct usb_anchor intr_anchor; | 185 | struct usb_anchor intr_anchor; |
178 | struct usb_anchor bulk_anchor; | 186 | struct usb_anchor bulk_anchor; |
187 | struct usb_anchor isoc_anchor; | ||
179 | 188 | ||
180 | struct usb_endpoint_descriptor *intr_ep; | 189 | struct usb_endpoint_descriptor *intr_ep; |
181 | struct usb_endpoint_descriptor *bulk_tx_ep; | 190 | struct usb_endpoint_descriptor *bulk_tx_ep; |
182 | struct usb_endpoint_descriptor *bulk_rx_ep; | 191 | struct usb_endpoint_descriptor *bulk_rx_ep; |
192 | struct usb_endpoint_descriptor *isoc_tx_ep; | ||
193 | struct usb_endpoint_descriptor *isoc_rx_ep; | ||
194 | |||
195 | int isoc_altsetting; | ||
183 | }; | 196 | }; |
184 | 197 | ||
185 | static void btusb_intr_complete(struct urb *urb) | 198 | static void btusb_intr_complete(struct urb *urb) |
@@ -195,6 +208,8 @@ static void btusb_intr_complete(struct urb *urb) | |||
195 | return; | 208 | return; |
196 | 209 | ||
197 | if (urb->status == 0) { | 210 | if (urb->status == 0) { |
211 | hdev->stat.byte_rx += urb->actual_length; | ||
212 | |||
198 | if (hci_recv_fragment(hdev, HCI_EVENT_PKT, | 213 | if (hci_recv_fragment(hdev, HCI_EVENT_PKT, |
199 | urb->transfer_buffer, | 214 | urb->transfer_buffer, |
200 | urb->actual_length) < 0) { | 215 | urb->actual_length) < 0) { |
@@ -216,7 +231,7 @@ static void btusb_intr_complete(struct urb *urb) | |||
216 | } | 231 | } |
217 | } | 232 | } |
218 | 233 | ||
219 | static inline int btusb_submit_intr_urb(struct hci_dev *hdev) | 234 | static int btusb_submit_intr_urb(struct hci_dev *hdev) |
220 | { | 235 | { |
221 | struct btusb_data *data = hdev->driver_data; | 236 | struct btusb_data *data = hdev->driver_data; |
222 | struct urb *urb; | 237 | struct urb *urb; |
@@ -226,6 +241,9 @@ static inline int btusb_submit_intr_urb(struct hci_dev *hdev) | |||
226 | 241 | ||
227 | BT_DBG("%s", hdev->name); | 242 | BT_DBG("%s", hdev->name); |
228 | 243 | ||
244 | if (!data->intr_ep) | ||
245 | return -ENODEV; | ||
246 | |||
229 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 247 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
230 | if (!urb) | 248 | if (!urb) |
231 | return -ENOMEM; | 249 | return -ENOMEM; |
@@ -274,6 +292,8 @@ static void btusb_bulk_complete(struct urb *urb) | |||
274 | return; | 292 | return; |
275 | 293 | ||
276 | if (urb->status == 0) { | 294 | if (urb->status == 0) { |
295 | hdev->stat.byte_rx += urb->actual_length; | ||
296 | |||
277 | if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT, | 297 | if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT, |
278 | urb->transfer_buffer, | 298 | urb->transfer_buffer, |
279 | urb->actual_length) < 0) { | 299 | urb->actual_length) < 0) { |
@@ -295,7 +315,7 @@ static void btusb_bulk_complete(struct urb *urb) | |||
295 | } | 315 | } |
296 | } | 316 | } |
297 | 317 | ||
298 | static inline int btusb_submit_bulk_urb(struct hci_dev *hdev) | 318 | static int btusb_submit_bulk_urb(struct hci_dev *hdev) |
299 | { | 319 | { |
300 | struct btusb_data *data = hdev->driver_data; | 320 | struct btusb_data *data = hdev->driver_data; |
301 | struct urb *urb; | 321 | struct urb *urb; |
@@ -305,6 +325,9 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev) | |||
305 | 325 | ||
306 | BT_DBG("%s", hdev->name); | 326 | BT_DBG("%s", hdev->name); |
307 | 327 | ||
328 | if (!data->bulk_rx_ep) | ||
329 | return -ENODEV; | ||
330 | |||
308 | urb = usb_alloc_urb(0, GFP_KERNEL); | 331 | urb = usb_alloc_urb(0, GFP_KERNEL); |
309 | if (!urb) | 332 | if (!urb) |
310 | return -ENOMEM; | 333 | return -ENOMEM; |
@@ -339,6 +362,127 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev) | |||
339 | return err; | 362 | return err; |
340 | } | 363 | } |
341 | 364 | ||
365 | static void btusb_isoc_complete(struct urb *urb) | ||
366 | { | ||
367 | struct hci_dev *hdev = urb->context; | ||
368 | struct btusb_data *data = hdev->driver_data; | ||
369 | int i, err; | ||
370 | |||
371 | BT_DBG("%s urb %p status %d count %d", hdev->name, | ||
372 | urb, urb->status, urb->actual_length); | ||
373 | |||
374 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | ||
375 | return; | ||
376 | |||
377 | if (urb->status == 0) { | ||
378 | for (i = 0; i < urb->number_of_packets; i++) { | ||
379 | unsigned int offset = urb->iso_frame_desc[i].offset; | ||
380 | unsigned int length = urb->iso_frame_desc[i].actual_length; | ||
381 | |||
382 | if (urb->iso_frame_desc[i].status) | ||
383 | continue; | ||
384 | |||
385 | hdev->stat.byte_rx += length; | ||
386 | |||
387 | if (hci_recv_fragment(hdev, HCI_SCODATA_PKT, | ||
388 | urb->transfer_buffer + offset, | ||
389 | length) < 0) { | ||
390 | BT_ERR("%s corrupted SCO packet", hdev->name); | ||
391 | hdev->stat.err_rx++; | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | |||
396 | if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags)) | ||
397 | return; | ||
398 | |||
399 | usb_anchor_urb(urb, &data->isoc_anchor); | ||
400 | |||
401 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
402 | if (err < 0) { | ||
403 | BT_ERR("%s urb %p failed to resubmit (%d)", | ||
404 | hdev->name, urb, -err); | ||
405 | usb_unanchor_urb(urb); | ||
406 | } | ||
407 | } | ||
408 | |||
409 | static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu) | ||
410 | { | ||
411 | int i, offset = 0; | ||
412 | |||
413 | BT_DBG("len %d mtu %d", len, mtu); | ||
414 | |||
415 | for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu; | ||
416 | i++, offset += mtu, len -= mtu) { | ||
417 | urb->iso_frame_desc[i].offset = offset; | ||
418 | urb->iso_frame_desc[i].length = mtu; | ||
419 | } | ||
420 | |||
421 | if (len && i < BTUSB_MAX_ISOC_FRAMES) { | ||
422 | urb->iso_frame_desc[i].offset = offset; | ||
423 | urb->iso_frame_desc[i].length = len; | ||
424 | i++; | ||
425 | } | ||
426 | |||
427 | urb->number_of_packets = i; | ||
428 | } | ||
429 | |||
430 | static int btusb_submit_isoc_urb(struct hci_dev *hdev) | ||
431 | { | ||
432 | struct btusb_data *data = hdev->driver_data; | ||
433 | struct urb *urb; | ||
434 | unsigned char *buf; | ||
435 | unsigned int pipe; | ||
436 | int err, size; | ||
437 | |||
438 | BT_DBG("%s", hdev->name); | ||
439 | |||
440 | if (!data->isoc_rx_ep) | ||
441 | return -ENODEV; | ||
442 | |||
443 | urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL); | ||
444 | if (!urb) | ||
445 | return -ENOMEM; | ||
446 | |||
447 | size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) * | ||
448 | BTUSB_MAX_ISOC_FRAMES; | ||
449 | |||
450 | buf = kmalloc(size, GFP_KERNEL); | ||
451 | if (!buf) { | ||
452 | usb_free_urb(urb); | ||
453 | return -ENOMEM; | ||
454 | } | ||
455 | |||
456 | pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress); | ||
457 | |||
458 | urb->dev = data->udev; | ||
459 | urb->pipe = pipe; | ||
460 | urb->context = hdev; | ||
461 | urb->complete = btusb_isoc_complete; | ||
462 | urb->interval = data->isoc_rx_ep->bInterval; | ||
463 | |||
464 | urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP; | ||
465 | urb->transfer_buffer = buf; | ||
466 | urb->transfer_buffer_length = size; | ||
467 | |||
468 | __fill_isoc_descriptor(urb, size, | ||
469 | le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize)); | ||
470 | |||
471 | usb_anchor_urb(urb, &data->isoc_anchor); | ||
472 | |||
473 | err = usb_submit_urb(urb, GFP_KERNEL); | ||
474 | if (err < 0) { | ||
475 | BT_ERR("%s urb %p submission failed (%d)", | ||
476 | hdev->name, urb, -err); | ||
477 | usb_unanchor_urb(urb); | ||
478 | kfree(buf); | ||
479 | } | ||
480 | |||
481 | usb_free_urb(urb); | ||
482 | |||
483 | return err; | ||
484 | } | ||
485 | |||
342 | static void btusb_tx_complete(struct urb *urb) | 486 | static void btusb_tx_complete(struct urb *urb) |
343 | { | 487 | { |
344 | struct sk_buff *skb = urb->context; | 488 | struct sk_buff *skb = urb->context; |
@@ -376,7 +520,7 @@ static int btusb_open(struct hci_dev *hdev) | |||
376 | 520 | ||
377 | err = btusb_submit_intr_urb(hdev); | 521 | err = btusb_submit_intr_urb(hdev); |
378 | if (err < 0) { | 522 | if (err < 0) { |
379 | clear_bit(BTUSB_INTR_RUNNING, &hdev->flags); | 523 | clear_bit(BTUSB_INTR_RUNNING, &data->flags); |
380 | clear_bit(HCI_RUNNING, &hdev->flags); | 524 | clear_bit(HCI_RUNNING, &hdev->flags); |
381 | } | 525 | } |
382 | 526 | ||
@@ -392,6 +536,11 @@ static int btusb_close(struct hci_dev *hdev) | |||
392 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) | 536 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) |
393 | return 0; | 537 | return 0; |
394 | 538 | ||
539 | cancel_work_sync(&data->work); | ||
540 | |||
541 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); | ||
542 | usb_kill_anchored_urbs(&data->isoc_anchor); | ||
543 | |||
395 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); | 544 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); |
396 | usb_kill_anchored_urbs(&data->bulk_anchor); | 545 | usb_kill_anchored_urbs(&data->bulk_anchor); |
397 | 546 | ||
@@ -453,6 +602,9 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
453 | break; | 602 | break; |
454 | 603 | ||
455 | case HCI_ACLDATA_PKT: | 604 | case HCI_ACLDATA_PKT: |
605 | if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1) | ||
606 | return -ENODEV; | ||
607 | |||
456 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 608 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
457 | if (!urb) | 609 | if (!urb) |
458 | return -ENOMEM; | 610 | return -ENOMEM; |
@@ -467,9 +619,31 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
467 | break; | 619 | break; |
468 | 620 | ||
469 | case HCI_SCODATA_PKT: | 621 | case HCI_SCODATA_PKT: |
622 | if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1) | ||
623 | return -ENODEV; | ||
624 | |||
625 | urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC); | ||
626 | if (!urb) | ||
627 | return -ENOMEM; | ||
628 | |||
629 | pipe = usb_sndisocpipe(data->udev, | ||
630 | data->isoc_tx_ep->bEndpointAddress); | ||
631 | |||
632 | urb->dev = data->udev; | ||
633 | urb->pipe = pipe; | ||
634 | urb->context = skb; | ||
635 | urb->complete = btusb_tx_complete; | ||
636 | urb->interval = data->isoc_tx_ep->bInterval; | ||
637 | |||
638 | urb->transfer_flags = URB_ISO_ASAP; | ||
639 | urb->transfer_buffer = skb->data; | ||
640 | urb->transfer_buffer_length = skb->len; | ||
641 | |||
642 | __fill_isoc_descriptor(urb, skb->len, | ||
643 | le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); | ||
644 | |||
470 | hdev->stat.sco_tx++; | 645 | hdev->stat.sco_tx++; |
471 | kfree_skb(skb); | 646 | break; |
472 | return 0; | ||
473 | 647 | ||
474 | default: | 648 | default: |
475 | return -EILSEQ; | 649 | return -EILSEQ; |
@@ -508,22 +682,86 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt) | |||
508 | schedule_work(&data->work); | 682 | schedule_work(&data->work); |
509 | } | 683 | } |
510 | 684 | ||
685 | static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting) | ||
686 | { | ||
687 | struct btusb_data *data = hdev->driver_data; | ||
688 | struct usb_interface *intf = data->isoc; | ||
689 | struct usb_endpoint_descriptor *ep_desc; | ||
690 | int i, err; | ||
691 | |||
692 | if (!data->isoc) | ||
693 | return -ENODEV; | ||
694 | |||
695 | err = usb_set_interface(data->udev, 1, altsetting); | ||
696 | if (err < 0) { | ||
697 | BT_ERR("%s setting interface failed (%d)", hdev->name, -err); | ||
698 | return err; | ||
699 | } | ||
700 | |||
701 | data->isoc_altsetting = altsetting; | ||
702 | |||
703 | data->isoc_tx_ep = NULL; | ||
704 | data->isoc_rx_ep = NULL; | ||
705 | |||
706 | for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { | ||
707 | ep_desc = &intf->cur_altsetting->endpoint[i].desc; | ||
708 | |||
709 | if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) { | ||
710 | data->isoc_tx_ep = ep_desc; | ||
711 | continue; | ||
712 | } | ||
713 | |||
714 | if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) { | ||
715 | data->isoc_rx_ep = ep_desc; | ||
716 | continue; | ||
717 | } | ||
718 | } | ||
719 | |||
720 | if (!data->isoc_tx_ep || !data->isoc_rx_ep) { | ||
721 | BT_ERR("%s invalid SCO descriptors", hdev->name); | ||
722 | return -ENODEV; | ||
723 | } | ||
724 | |||
725 | return 0; | ||
726 | } | ||
727 | |||
511 | static void btusb_work(struct work_struct *work) | 728 | static void btusb_work(struct work_struct *work) |
512 | { | 729 | { |
513 | struct btusb_data *data = container_of(work, struct btusb_data, work); | 730 | struct btusb_data *data = container_of(work, struct btusb_data, work); |
514 | struct hci_dev *hdev = data->hdev; | 731 | struct hci_dev *hdev = data->hdev; |
515 | 732 | ||
516 | if (hdev->conn_hash.acl_num == 0) { | 733 | if (hdev->conn_hash.acl_num > 0) { |
734 | if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) { | ||
735 | if (btusb_submit_bulk_urb(hdev) < 0) | ||
736 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); | ||
737 | else | ||
738 | btusb_submit_bulk_urb(hdev); | ||
739 | } | ||
740 | } else { | ||
517 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); | 741 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); |
518 | usb_kill_anchored_urbs(&data->bulk_anchor); | 742 | usb_kill_anchored_urbs(&data->bulk_anchor); |
519 | return; | ||
520 | } | 743 | } |
521 | 744 | ||
522 | if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) { | 745 | if (hdev->conn_hash.sco_num > 0) { |
523 | if (btusb_submit_bulk_urb(hdev) < 0) | 746 | if (data->isoc_altsetting != 2) { |
524 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); | 747 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); |
525 | else | 748 | usb_kill_anchored_urbs(&data->isoc_anchor); |
526 | btusb_submit_bulk_urb(hdev); | 749 | |
750 | if (__set_isoc_interface(hdev, 2) < 0) | ||
751 | return; | ||
752 | } | ||
753 | |||
754 | if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) { | ||
755 | if (btusb_submit_isoc_urb(hdev) < 0) | ||
756 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); | ||
757 | else | ||
758 | btusb_submit_isoc_urb(hdev); | ||
759 | } | ||
760 | } else { | ||
761 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); | ||
762 | usb_kill_anchored_urbs(&data->isoc_anchor); | ||
763 | |||
764 | __set_isoc_interface(hdev, 0); | ||
527 | } | 765 | } |
528 | } | 766 | } |
529 | 767 | ||
@@ -589,6 +827,7 @@ static int btusb_probe(struct usb_interface *intf, | |||
589 | } | 827 | } |
590 | 828 | ||
591 | data->udev = interface_to_usbdev(intf); | 829 | data->udev = interface_to_usbdev(intf); |
830 | data->intf = intf; | ||
592 | 831 | ||
593 | spin_lock_init(&data->lock); | 832 | spin_lock_init(&data->lock); |
594 | 833 | ||
@@ -597,6 +836,7 @@ static int btusb_probe(struct usb_interface *intf, | |||
597 | init_usb_anchor(&data->tx_anchor); | 836 | init_usb_anchor(&data->tx_anchor); |
598 | init_usb_anchor(&data->intr_anchor); | 837 | init_usb_anchor(&data->intr_anchor); |
599 | init_usb_anchor(&data->bulk_anchor); | 838 | init_usb_anchor(&data->bulk_anchor); |
839 | init_usb_anchor(&data->isoc_anchor); | ||
600 | 840 | ||
601 | hdev = hci_alloc_dev(); | 841 | hdev = hci_alloc_dev(); |
602 | if (!hdev) { | 842 | if (!hdev) { |
@@ -620,6 +860,9 @@ static int btusb_probe(struct usb_interface *intf, | |||
620 | 860 | ||
621 | hdev->owner = THIS_MODULE; | 861 | hdev->owner = THIS_MODULE; |
622 | 862 | ||
863 | /* interface numbers are hardcoded in the spec */ | ||
864 | data->isoc = usb_ifnum_to_if(data->udev, 1); | ||
865 | |||
623 | if (reset || id->driver_info & BTUSB_RESET) | 866 | if (reset || id->driver_info & BTUSB_RESET) |
624 | set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); | 867 | set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); |
625 | 868 | ||
@@ -628,11 +871,16 @@ static int btusb_probe(struct usb_interface *intf, | |||
628 | set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks); | 871 | set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks); |
629 | } | 872 | } |
630 | 873 | ||
874 | if (id->driver_info & BTUSB_BROKEN_ISOC) | ||
875 | data->isoc = NULL; | ||
876 | |||
631 | if (id->driver_info & BTUSB_SNIFFER) { | 877 | if (id->driver_info & BTUSB_SNIFFER) { |
632 | struct usb_device *udev = interface_to_usbdev(intf); | 878 | struct usb_device *udev = data->udev; |
633 | 879 | ||
634 | if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) | 880 | if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) |
635 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); | 881 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); |
882 | |||
883 | data->isoc = NULL; | ||
636 | } | 884 | } |
637 | 885 | ||
638 | if (id->driver_info & BTUSB_BCM92035) { | 886 | if (id->driver_info & BTUSB_BCM92035) { |
@@ -646,6 +894,16 @@ static int btusb_probe(struct usb_interface *intf, | |||
646 | } | 894 | } |
647 | } | 895 | } |
648 | 896 | ||
897 | if (data->isoc) { | ||
898 | err = usb_driver_claim_interface(&btusb_driver, | ||
899 | data->isoc, data); | ||
900 | if (err < 0) { | ||
901 | hci_free_dev(hdev); | ||
902 | kfree(data); | ||
903 | return err; | ||
904 | } | ||
905 | } | ||
906 | |||
649 | err = hci_register_dev(hdev); | 907 | err = hci_register_dev(hdev); |
650 | if (err < 0) { | 908 | if (err < 0) { |
651 | hci_free_dev(hdev); | 909 | hci_free_dev(hdev); |
@@ -670,10 +928,22 @@ static void btusb_disconnect(struct usb_interface *intf) | |||
670 | 928 | ||
671 | hdev = data->hdev; | 929 | hdev = data->hdev; |
672 | 930 | ||
673 | usb_set_intfdata(intf, NULL); | 931 | __hci_dev_hold(hdev); |
932 | |||
933 | usb_set_intfdata(data->intf, NULL); | ||
934 | |||
935 | if (data->isoc) | ||
936 | usb_set_intfdata(data->isoc, NULL); | ||
674 | 937 | ||
675 | hci_unregister_dev(hdev); | 938 | hci_unregister_dev(hdev); |
676 | 939 | ||
940 | if (intf == data->isoc) | ||
941 | usb_driver_release_interface(&btusb_driver, data->intf); | ||
942 | else if (data->isoc) | ||
943 | usb_driver_release_interface(&btusb_driver, data->isoc); | ||
944 | |||
945 | __hci_dev_put(hdev); | ||
946 | |||
677 | hci_free_dev(hdev); | 947 | hci_free_dev(hdev); |
678 | } | 948 | } |
679 | 949 | ||