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