diff options
Diffstat (limited to 'drivers/bluetooth/hci_usb.c')
-rw-r--r-- | drivers/bluetooth/hci_usb.c | 99 |
1 files changed, 97 insertions, 2 deletions
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index a7d9d7e99e72..e2d4beac7420 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c | |||
@@ -67,6 +67,8 @@ static int ignore = 0; | |||
67 | static int ignore_dga = 0; | 67 | static int ignore_dga = 0; |
68 | static int ignore_csr = 0; | 68 | static int ignore_csr = 0; |
69 | static int ignore_sniffer = 0; | 69 | static int ignore_sniffer = 0; |
70 | static int disable_scofix = 0; | ||
71 | static int force_scofix = 0; | ||
70 | static int reset = 0; | 72 | static int reset = 0; |
71 | 73 | ||
72 | #ifdef CONFIG_BT_HCIUSB_SCO | 74 | #ifdef CONFIG_BT_HCIUSB_SCO |
@@ -107,9 +109,12 @@ static struct usb_device_id blacklist_ids[] = { | |||
107 | { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, | 109 | { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, |
108 | 110 | ||
109 | /* Broadcom BCM2035 */ | 111 | /* Broadcom BCM2035 */ |
110 | { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_BROKEN_ISOC }, | 112 | { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU }, |
111 | { USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_BCM92035 }, | 113 | { USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_BCM92035 }, |
112 | 114 | ||
115 | /* IBM/Lenovo ThinkPad with Broadcom chip */ | ||
116 | { USB_DEVICE(0x0a5c, 0x201e), .driver_info = HCI_WRONG_SCO_MTU }, | ||
117 | |||
113 | /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ | 118 | /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ |
114 | { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, | 119 | { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, |
115 | 120 | ||
@@ -119,8 +124,13 @@ static struct usb_device_id blacklist_ids[] = { | |||
119 | /* ISSC Bluetooth Adapter v3.1 */ | 124 | /* ISSC Bluetooth Adapter v3.1 */ |
120 | { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, | 125 | { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, |
121 | 126 | ||
122 | /* RTX Telecom based adapter with buggy SCO support */ | 127 | /* RTX Telecom based adapters with buggy SCO support */ |
123 | { USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC }, | 128 | { USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC }, |
129 | { USB_DEVICE(0x0400, 0x080a), .driver_info = HCI_BROKEN_ISOC }, | ||
130 | |||
131 | /* Belkin F8T012 and F8T013 devices */ | ||
132 | { USB_DEVICE(0x050d, 0x0012), .driver_info = HCI_WRONG_SCO_MTU }, | ||
133 | { USB_DEVICE(0x050d, 0x0013), .driver_info = HCI_WRONG_SCO_MTU }, | ||
124 | 134 | ||
125 | /* Digianswer devices */ | 135 | /* Digianswer devices */ |
126 | { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER }, | 136 | { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER }, |
@@ -129,6 +139,9 @@ static struct usb_device_id blacklist_ids[] = { | |||
129 | /* CSR BlueCore Bluetooth Sniffer */ | 139 | /* CSR BlueCore Bluetooth Sniffer */ |
130 | { USB_DEVICE(0x0a12, 0x0002), .driver_info = HCI_SNIFFER }, | 140 | { USB_DEVICE(0x0a12, 0x0002), .driver_info = HCI_SNIFFER }, |
131 | 141 | ||
142 | /* Frontline ComProbe Bluetooth Sniffer */ | ||
143 | { USB_DEVICE(0x16d3, 0x0002), .driver_info = HCI_SNIFFER }, | ||
144 | |||
132 | { } /* Terminating entry */ | 145 | { } /* Terminating entry */ |
133 | }; | 146 | }; |
134 | 147 | ||
@@ -984,6 +997,11 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id | |||
984 | if (reset || id->driver_info & HCI_RESET) | 997 | if (reset || id->driver_info & HCI_RESET) |
985 | set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); | 998 | set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); |
986 | 999 | ||
1000 | if (force_scofix || id->driver_info & HCI_WRONG_SCO_MTU) { | ||
1001 | if (!disable_scofix) | ||
1002 | set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks); | ||
1003 | } | ||
1004 | |||
987 | if (id->driver_info & HCI_SNIFFER) { | 1005 | if (id->driver_info & HCI_SNIFFER) { |
988 | if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) | 1006 | if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) |
989 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); | 1007 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); |
@@ -1042,10 +1060,81 @@ static void hci_usb_disconnect(struct usb_interface *intf) | |||
1042 | hci_free_dev(hdev); | 1060 | hci_free_dev(hdev); |
1043 | } | 1061 | } |
1044 | 1062 | ||
1063 | static int hci_usb_suspend(struct usb_interface *intf, pm_message_t message) | ||
1064 | { | ||
1065 | struct hci_usb *husb = usb_get_intfdata(intf); | ||
1066 | struct list_head killed; | ||
1067 | unsigned long flags; | ||
1068 | int i; | ||
1069 | |||
1070 | if (!husb || intf == husb->isoc_iface) | ||
1071 | return 0; | ||
1072 | |||
1073 | hci_suspend_dev(husb->hdev); | ||
1074 | |||
1075 | INIT_LIST_HEAD(&killed); | ||
1076 | |||
1077 | for (i = 0; i < 4; i++) { | ||
1078 | struct _urb_queue *q = &husb->pending_q[i]; | ||
1079 | struct _urb *_urb, *_tmp; | ||
1080 | |||
1081 | while ((_urb = _urb_dequeue(q))) { | ||
1082 | /* reset queue since _urb_dequeue sets it to NULL */ | ||
1083 | _urb->queue = q; | ||
1084 | usb_kill_urb(&_urb->urb); | ||
1085 | list_add(&_urb->list, &killed); | ||
1086 | } | ||
1087 | |||
1088 | spin_lock_irqsave(&q->lock, flags); | ||
1089 | |||
1090 | list_for_each_entry_safe(_urb, _tmp, &killed, list) { | ||
1091 | list_move_tail(&_urb->list, &q->head); | ||
1092 | } | ||
1093 | |||
1094 | spin_unlock_irqrestore(&q->lock, flags); | ||
1095 | } | ||
1096 | |||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | static int hci_usb_resume(struct usb_interface *intf) | ||
1101 | { | ||
1102 | struct hci_usb *husb = usb_get_intfdata(intf); | ||
1103 | unsigned long flags; | ||
1104 | int i, err = 0; | ||
1105 | |||
1106 | if (!husb || intf == husb->isoc_iface) | ||
1107 | return 0; | ||
1108 | |||
1109 | for (i = 0; i < 4; i++) { | ||
1110 | struct _urb_queue *q = &husb->pending_q[i]; | ||
1111 | struct _urb *_urb; | ||
1112 | |||
1113 | spin_lock_irqsave(&q->lock, flags); | ||
1114 | |||
1115 | list_for_each_entry(_urb, &q->head, list) { | ||
1116 | err = usb_submit_urb(&_urb->urb, GFP_ATOMIC); | ||
1117 | if (err) | ||
1118 | break; | ||
1119 | } | ||
1120 | |||
1121 | spin_unlock_irqrestore(&q->lock, flags); | ||
1122 | |||
1123 | if (err) | ||
1124 | return -EIO; | ||
1125 | } | ||
1126 | |||
1127 | hci_resume_dev(husb->hdev); | ||
1128 | |||
1129 | return 0; | ||
1130 | } | ||
1131 | |||
1045 | static struct usb_driver hci_usb_driver = { | 1132 | static struct usb_driver hci_usb_driver = { |
1046 | .name = "hci_usb", | 1133 | .name = "hci_usb", |
1047 | .probe = hci_usb_probe, | 1134 | .probe = hci_usb_probe, |
1048 | .disconnect = hci_usb_disconnect, | 1135 | .disconnect = hci_usb_disconnect, |
1136 | .suspend = hci_usb_suspend, | ||
1137 | .resume = hci_usb_resume, | ||
1049 | .id_table = bluetooth_ids, | 1138 | .id_table = bluetooth_ids, |
1050 | }; | 1139 | }; |
1051 | 1140 | ||
@@ -1081,6 +1170,12 @@ MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001"); | |||
1081 | module_param(ignore_sniffer, bool, 0644); | 1170 | module_param(ignore_sniffer, bool, 0644); |
1082 | MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002"); | 1171 | MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002"); |
1083 | 1172 | ||
1173 | module_param(disable_scofix, bool, 0644); | ||
1174 | MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size"); | ||
1175 | |||
1176 | module_param(force_scofix, bool, 0644); | ||
1177 | MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size"); | ||
1178 | |||
1084 | module_param(reset, bool, 0644); | 1179 | module_param(reset, bool, 0644); |
1085 | MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); | 1180 | MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); |
1086 | 1181 | ||