diff options
Diffstat (limited to 'drivers/bluetooth/hci_usb.c')
-rw-r--r-- | drivers/bluetooth/hci_usb.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index a7d9d7e99e72..6a0c2230f82f 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c | |||
@@ -122,6 +122,9 @@ static struct usb_device_id blacklist_ids[] = { | |||
122 | /* RTX Telecom based adapter with buggy SCO support */ | 122 | /* RTX Telecom based adapter with buggy SCO support */ |
123 | { USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC }, | 123 | { USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC }, |
124 | 124 | ||
125 | /* Belkin F8T012 */ | ||
126 | { USB_DEVICE(0x050d, 0x0012), .driver_info = HCI_WRONG_SCO_MTU }, | ||
127 | |||
125 | /* Digianswer devices */ | 128 | /* Digianswer devices */ |
126 | { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER }, | 129 | { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER }, |
127 | { USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE }, | 130 | { USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE }, |
@@ -129,6 +132,9 @@ static struct usb_device_id blacklist_ids[] = { | |||
129 | /* CSR BlueCore Bluetooth Sniffer */ | 132 | /* CSR BlueCore Bluetooth Sniffer */ |
130 | { USB_DEVICE(0x0a12, 0x0002), .driver_info = HCI_SNIFFER }, | 133 | { USB_DEVICE(0x0a12, 0x0002), .driver_info = HCI_SNIFFER }, |
131 | 134 | ||
135 | /* Frontline ComProbe Bluetooth Sniffer */ | ||
136 | { USB_DEVICE(0x16d3, 0x0002), .driver_info = HCI_SNIFFER }, | ||
137 | |||
132 | { } /* Terminating entry */ | 138 | { } /* Terminating entry */ |
133 | }; | 139 | }; |
134 | 140 | ||
@@ -984,6 +990,9 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id | |||
984 | if (reset || id->driver_info & HCI_RESET) | 990 | if (reset || id->driver_info & HCI_RESET) |
985 | set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); | 991 | set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); |
986 | 992 | ||
993 | if (id->driver_info & HCI_WRONG_SCO_MTU) | ||
994 | set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks); | ||
995 | |||
987 | if (id->driver_info & HCI_SNIFFER) { | 996 | if (id->driver_info & HCI_SNIFFER) { |
988 | if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) | 997 | if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) |
989 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); | 998 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); |
@@ -1042,10 +1051,81 @@ static void hci_usb_disconnect(struct usb_interface *intf) | |||
1042 | hci_free_dev(hdev); | 1051 | hci_free_dev(hdev); |
1043 | } | 1052 | } |
1044 | 1053 | ||
1054 | static int hci_usb_suspend(struct usb_interface *intf, pm_message_t message) | ||
1055 | { | ||
1056 | struct hci_usb *husb = usb_get_intfdata(intf); | ||
1057 | struct list_head killed; | ||
1058 | unsigned long flags; | ||
1059 | int i; | ||
1060 | |||
1061 | if (!husb || intf == husb->isoc_iface) | ||
1062 | return 0; | ||
1063 | |||
1064 | hci_suspend_dev(husb->hdev); | ||
1065 | |||
1066 | INIT_LIST_HEAD(&killed); | ||
1067 | |||
1068 | for (i = 0; i < 4; i++) { | ||
1069 | struct _urb_queue *q = &husb->pending_q[i]; | ||
1070 | struct _urb *_urb, *_tmp; | ||
1071 | |||
1072 | while ((_urb = _urb_dequeue(q))) { | ||
1073 | /* reset queue since _urb_dequeue sets it to NULL */ | ||
1074 | _urb->queue = q; | ||
1075 | usb_kill_urb(&_urb->urb); | ||
1076 | list_add(&_urb->list, &killed); | ||
1077 | } | ||
1078 | |||
1079 | spin_lock_irqsave(&q->lock, flags); | ||
1080 | |||
1081 | list_for_each_entry_safe(_urb, _tmp, &killed, list) { | ||
1082 | list_move_tail(&_urb->list, &q->head); | ||
1083 | } | ||
1084 | |||
1085 | spin_unlock_irqrestore(&q->lock, flags); | ||
1086 | } | ||
1087 | |||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | static int hci_usb_resume(struct usb_interface *intf) | ||
1092 | { | ||
1093 | struct hci_usb *husb = usb_get_intfdata(intf); | ||
1094 | unsigned long flags; | ||
1095 | int i, err = 0; | ||
1096 | |||
1097 | if (!husb || intf == husb->isoc_iface) | ||
1098 | return 0; | ||
1099 | |||
1100 | for (i = 0; i < 4; i++) { | ||
1101 | struct _urb_queue *q = &husb->pending_q[i]; | ||
1102 | struct _urb *_urb; | ||
1103 | |||
1104 | spin_lock_irqsave(&q->lock, flags); | ||
1105 | |||
1106 | list_for_each_entry(_urb, &q->head, list) { | ||
1107 | err = usb_submit_urb(&_urb->urb, GFP_ATOMIC); | ||
1108 | if (err) | ||
1109 | break; | ||
1110 | } | ||
1111 | |||
1112 | spin_unlock_irqrestore(&q->lock, flags); | ||
1113 | |||
1114 | if (err) | ||
1115 | return -EIO; | ||
1116 | } | ||
1117 | |||
1118 | hci_resume_dev(husb->hdev); | ||
1119 | |||
1120 | return 0; | ||
1121 | } | ||
1122 | |||
1045 | static struct usb_driver hci_usb_driver = { | 1123 | static struct usb_driver hci_usb_driver = { |
1046 | .name = "hci_usb", | 1124 | .name = "hci_usb", |
1047 | .probe = hci_usb_probe, | 1125 | .probe = hci_usb_probe, |
1048 | .disconnect = hci_usb_disconnect, | 1126 | .disconnect = hci_usb_disconnect, |
1127 | .suspend = hci_usb_suspend, | ||
1128 | .resume = hci_usb_resume, | ||
1049 | .id_table = bluetooth_ids, | 1129 | .id_table = bluetooth_ids, |
1050 | }; | 1130 | }; |
1051 | 1131 | ||