Commit 430e67b3 authored by Marcel Holtmann's avatar Marcel Holtmann

[Bluetooth] Send HCI_Reset for some Broadcom dongles

This patch introduces a quirk flag for sending the HCI_Reset command. In
general the HCI_Reset is not needed, but some Broadcom dongles uses this
reset command to switch from HID to HCI mode. And it is not safe to send
the HCI_Reset to every Bluetooth device, because the CSR firmware prior
HCI 12.x will reset the host transport and this is wrong according to the
Bluetooth specification.
parent dc42ad2c
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* *
* $Id: hci_usb.c,v 1.8 2002/07/18 17:23:09 maxk Exp $ * $Id: hci_usb.c,v 1.8 2002/07/18 17:23:09 maxk Exp $
*/ */
#define VERSION "2.4" #define VERSION "2.5"
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -70,12 +70,6 @@ ...@@ -70,12 +70,6 @@
static struct usb_driver hci_usb_driver; static struct usb_driver hci_usb_driver;
static struct usb_device_id bluetooth_ids[] = { static struct usb_device_id bluetooth_ids[] = {
/* Broadcom BCM2033 without firmware */
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
/* Digianswer device */
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
/* Generic Bluetooth USB device */ /* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) }, { USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) },
...@@ -93,6 +87,19 @@ static struct usb_device_id bluetooth_ids[] = { ...@@ -93,6 +87,19 @@ static struct usb_device_id bluetooth_ids[] = {
MODULE_DEVICE_TABLE (usb, bluetooth_ids); MODULE_DEVICE_TABLE (usb, bluetooth_ids);
static struct usb_device_id blacklist_ids[] = {
/* Broadcom BCM2033 without firmware */
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET },
/* Digianswer device */
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
{ } /* Terminating entry */
};
struct _urb *_urb_alloc(int isoc, int gfp) struct _urb *_urb_alloc(int isoc, int gfp)
{ {
struct _urb *_urb = kmalloc(sizeof(struct _urb) + struct _urb *_urb = kmalloc(sizeof(struct _urb) +
...@@ -790,6 +797,13 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -790,6 +797,13 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
BT_DBG("udev %p ifnum %d", udev, ifnum); BT_DBG("udev %p ifnum %d", udev, ifnum);
if (!id->driver_info) {
const struct usb_device_id *match;
match = usb_match_id(intf, blacklist_ids);
if (match)
id = match;
}
iface = udev->actconfig->interface[0]; iface = udev->actconfig->interface[0];
if (id->driver_info & HCI_IGNORE) if (id->driver_info & HCI_IGNORE)
...@@ -928,6 +942,9 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -928,6 +942,9 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
hdev->owner = THIS_MODULE; hdev->owner = THIS_MODULE;
if (id->driver_info & HCI_RESET)
set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device"); BT_ERR("Can't register HCI device");
hci_free_dev(hdev); hci_free_dev(hdev);
...@@ -994,6 +1011,6 @@ void hci_usb_cleanup(void) ...@@ -994,6 +1011,6 @@ void hci_usb_cleanup(void)
module_init(hci_usb_init); module_init(hci_usb_init);
module_exit(hci_usb_cleanup); module_exit(hci_usb_cleanup);
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>"); MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION); MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -38,7 +38,8 @@ ...@@ -38,7 +38,8 @@
#define HCI_DIGI_REQ 0x40 #define HCI_DIGI_REQ 0x40
#define HCI_IGNORE 0x01 #define HCI_IGNORE 0x01
#define HCI_DIGIANSWER 0x02 #define HCI_RESET 0x02
#define HCI_DIGIANSWER 0x04
#define HCI_MAX_IFACE_NUM 3 #define HCI_MAX_IFACE_NUM 3
......
...@@ -50,6 +50,11 @@ ...@@ -50,6 +50,11 @@
#define HCI_RS232 4 #define HCI_RS232 4
#define HCI_PCI 5 #define HCI_PCI 5
/* HCI device quirks */
enum {
HCI_QUIRK_RESET_ON_INIT
};
/* HCI device flags */ /* HCI device flags */
enum { enum {
HCI_UP, HCI_UP,
......
...@@ -77,6 +77,8 @@ struct hci_dev { ...@@ -77,6 +77,8 @@ struct hci_dev {
__u16 link_policy; __u16 link_policy;
__u16 link_mode; __u16 link_mode;
unsigned long quirks;
atomic_t cmd_cnt; atomic_t cmd_cnt;
unsigned int acl_cnt; unsigned int acl_cnt;
unsigned int sco_cnt; unsigned int sco_cnt;
......
...@@ -189,6 +189,10 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) ...@@ -189,6 +189,10 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
/* Mandatory initialization */ /* Mandatory initialization */
/* Reset */
if (test_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks))
hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL);
/* Read Local Supported Features */ /* Read Local Supported Features */
hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL); hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment