aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/hci_usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/hci_usb.c')
-rw-r--r--drivers/bluetooth/hci_usb.c99
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;
67static int ignore_dga = 0; 67static int ignore_dga = 0;
68static int ignore_csr = 0; 68static int ignore_csr = 0;
69static int ignore_sniffer = 0; 69static int ignore_sniffer = 0;
70static int disable_scofix = 0;
71static int force_scofix = 0;
70static int reset = 0; 72static 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
1063static 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
1100static 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
1045static struct usb_driver hci_usb_driver = { 1132static 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");
1081module_param(ignore_sniffer, bool, 0644); 1170module_param(ignore_sniffer, bool, 0644);
1082MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002"); 1171MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
1083 1172
1173module_param(disable_scofix, bool, 0644);
1174MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
1175
1176module_param(force_scofix, bool, 0644);
1177MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size");
1178
1084module_param(reset, bool, 0644); 1179module_param(reset, bool, 0644);
1085MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); 1180MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
1086 1181