From 430e67b3c11621bb1b6d10677644b9bc91893ce1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 5 Mar 2004 19:27:52 +0100 Subject: [PATCH] [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. --- drivers/bluetooth/hci_usb.c | 35 ++++++++++++++++++++++++-------- drivers/bluetooth/hci_usb.h | 3 ++- include/net/bluetooth/hci.h | 5 +++++ include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_core.c | 4 ++++ 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index c0feb4fd22232..e288e65947d96 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -31,7 +31,7 @@ * * $Id: hci_usb.c,v 1.8 2002/07/18 17:23:09 maxk Exp $ */ -#define VERSION "2.4" +#define VERSION "2.5" #include #include @@ -70,12 +70,6 @@ static struct usb_driver hci_usb_driver; 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 */ { USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) }, @@ -93,6 +87,19 @@ static struct usb_device_id 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 = kmalloc(sizeof(struct _urb) + @@ -644,7 +651,7 @@ static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int c #endif } BT_DBG("new packet len %d", len); - + skb = bt_skb_alloc(len, GFP_ATOMIC); if (!skb) { BT_ERR("%s no memory for the packet", husb->hdev->name); @@ -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); + 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]; if (id->driver_info & HCI_IGNORE) @@ -928,6 +942,9 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) 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) { BT_ERR("Can't register HCI device"); hci_free_dev(hdev); @@ -994,6 +1011,6 @@ void hci_usb_cleanup(void) module_init(hci_usb_init); module_exit(hci_usb_cleanup); -MODULE_AUTHOR("Maxim Krasnyansky "); +MODULE_AUTHOR("Maxim Krasnyansky , Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h index 09381b215bf17..94437b0c89aaa 100644 --- a/drivers/bluetooth/hci_usb.h +++ b/drivers/bluetooth/hci_usb.h @@ -38,7 +38,8 @@ #define HCI_DIGI_REQ 0x40 #define HCI_IGNORE 0x01 -#define HCI_DIGIANSWER 0x02 +#define HCI_RESET 0x02 +#define HCI_DIGIANSWER 0x04 #define HCI_MAX_IFACE_NUM 3 diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 39bce6f7bd5d9..6f235638a7acd 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -50,6 +50,11 @@ #define HCI_RS232 4 #define HCI_PCI 5 +/* HCI device quirks */ +enum { + HCI_QUIRK_RESET_ON_INIT +}; + /* HCI device flags */ enum { HCI_UP, diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4ce3430b34edb..9e1278484a50e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -77,6 +77,8 @@ struct hci_dev { __u16 link_policy; __u16 link_mode; + unsigned long quirks; + atomic_t cmd_cnt; unsigned int acl_cnt; unsigned int sco_cnt; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 77e7e9b7fcc97..35a874bde343c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -189,6 +189,10 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) /* 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 */ hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL); -- 2.53.0