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 | ||
