diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c old mode 100644 new mode 100755 index 6bacef3..7d20946 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -29,6 +29,8 @@ #include #include +#include "btusb.h" + #define VERSION "1.0" #define ATH3K_DNLOAD 0x01 @@ -68,7 +70,7 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x03F0, 0x311D) }, /* Atheros AR3012 with sflash firmware*/ - { USB_DEVICE(0x0CF3, 0x3004) }, + /* { USB_DEVICE(0x0CF3, 0x3004) }, */ /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -390,7 +392,7 @@ static int ath3k_probe(struct usb_interface *intf, BT_ERR("Set normal mode failed"); return ret; } - ath3k_switch_pid(udev); + /* ath3k_switch_pid(udev); */ return 0; } @@ -417,15 +419,23 @@ static struct usb_driver ath3k_driver = { .id_table = ath3k_table, }; +static struct btusb_quirk_device ath3k_device = { + .id = BTUSB_QUIRKY_ATH3k, + .probe = ath3k_probe, + .disconnect = ath3k_disconnect, +}; + static int __init ath3k_init(void) { BT_INFO("Atheros AR30xx firmware driver ver %s", VERSION); + btusb_register_quirky_device(&ath3k_device); return usb_register(&ath3k_driver); } static void __exit ath3k_exit(void) { usb_deregister(&ath3k_driver); + btusb_unregister_quirky_device(&ath3k_device); } module_init(ath3k_init); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c old mode 100644 new mode 100755 index c2de895..b7928c6 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -35,6 +35,8 @@ #include #include +#include "btusb.h" + #define VERSION "0.6" static int ignore_dga; @@ -47,6 +49,8 @@ static int reset = 1; static struct usb_driver btusb_driver; +static struct btusb_quirky_device *quirky_device[BTUSB_MAX_QUIRKY_DEVICE]; + #define BTUSB_IGNORE 0x01 #define BTUSB_DIGIANSWER 0x02 #define BTUSB_CSR 0x04 @@ -54,6 +58,7 @@ static struct usb_driver btusb_driver; #define BTUSB_BCM92035 0x10 #define BTUSB_BROKEN_ISOC 0x20 #define BTUSB_WRONG_SCO_MTU 0x40 +#define BTUSB_ATH301X 0x80 static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -110,7 +115,7 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, /* Atheros 3012 with sflash firmware */ - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH301X }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, @@ -1029,6 +1034,13 @@ static int btusb_probe(struct usb_interface *intf, } } + if (id->driver_info & BTUSB_ATH301X) { + struct btusb_quirk_device *ath3k = quirky_device[BTUSB_QUIRKY_ATH3k]; + if(ath3k) { + ath3k->probe(intf, id); + } + } + if (data->isoc) { err = usb_driver_claim_interface(&btusb_driver, data->isoc, data); @@ -1055,6 +1067,7 @@ static void btusb_disconnect(struct usb_interface *intf) { struct btusb_data *data = usb_get_intfdata(intf); struct hci_dev *hdev; + struct usb_device_id *id; BT_DBG("intf %p", intf); @@ -1080,6 +1093,14 @@ static void btusb_disconnect(struct usb_interface *intf) __hci_dev_put(hdev); hci_free_dev(hdev); + + id = usb_match_id(intf, blacklist_table); + if(id && (id->driver_info & BTUSB_ATH301X)) { + struct btusb_quirk_device *ath3k = quirky_device[BTUSB_QUIRKY_ATH3k]; + if(ath3k) { + ath3k->disconnect(id); + } + } } #ifdef CONFIG_PM @@ -1195,6 +1216,32 @@ static struct usb_driver btusb_driver = { .supports_autosuspend = 1, }; +int btusb_register_quirky_device(struct btusb_quirk_device *dev) +{ + if (dev->id >= BTUSB_MAX_QUIRKY_DEVICE) + return -EINVAL; + + if (quirky_device[dev->id]) + return -EEXIST; + + quirky_device[dev->id] = dev; + + return 0; +} + +int btusb_unregister_quirky_device(struct btusb_quirk_device *dev) +{ + if (dev->id >= BTUSB_MAX_QUIRKY_DEVICE) + return -EINVAL; + + if (!quirky_device[dev->id]) + return -EINVAL; + + quirky_device[dev->id] = NULL; + + return 0; +} + static int __init btusb_init(void) { BT_INFO("Generic Bluetooth USB driver ver %s", VERSION); @@ -1207,6 +1254,9 @@ static void __exit btusb_exit(void) usb_deregister(&btusb_driver); } +EXPORT_SYMBOL_GPL(btusb_register_quirky_device); +EXPORT_SYMBOL_GPL(btusb_unregister_quirky_device); + module_init(btusb_init); module_exit(btusb_exit); diff --git a/drivers/bluetooth/btusb.h b/drivers/bluetooth/btusb.h new file mode 100755 index 0000000..d1cbc75 --- /dev/null +++ b/drivers/bluetooth/btusb.h @@ -0,0 +1,36 @@ +/* + * + * Generic Bluetooth USB driver + * + * Copyright (C) 2005-2008 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#define BTUSB_MAX_QUIRKY_DEVICE 1 + +#define BTUSB_QUIRKY_ATH3k 0 + +struct btusb_quirk_device { + unsigned int id; + int (*probe)(struct usb_interface *intf, + const struct usb_device_id *id); + void (*disconnect)(struct usb_interface *intf); +}; + +int btusb_register_quirky_device(struct btusb_quirk_device *dev); +int btusb_unregister_quirky_device(struct btusb_quirk_device *dev);