Index: chromeos/compat-wireless/drivers/bluetooth/btusb.c |
diff --git a/chromeos/compat-wireless/drivers/bluetooth/btusb.c b/chromeos/compat-wireless/drivers/bluetooth/btusb.c |
index d22ce3cc611e7bb60f0377ff344fa41fb7bde2db..13e0fb845e1069312bd66e7206a1a259a29225d7 100644 |
--- a/chromeos/compat-wireless/drivers/bluetooth/btusb.c |
+++ b/chromeos/compat-wireless/drivers/bluetooth/btusb.c |
@@ -34,6 +34,7 @@ |
#include <net/bluetooth/bluetooth.h> |
#include <net/bluetooth/hci_core.h> |
+#include "fwload.h" |
#define VERSION "0.6" |
@@ -55,6 +56,26 @@ static struct usb_driver btusb_driver; |
#define BTUSB_BROKEN_ISOC 0x20 |
#define BTUSB_WRONG_SCO_MTU 0x40 |
+static struct usb_device_id ath_table[] = { |
+ /* Atheros AR3011 */ |
+ { USB_DEVICE(0x0CF3, 0x3002) }, |
+ { USB_DEVICE(0x13D3, 0x3304) }, |
+ { } /* Terminating entry */ |
+}; |
+ |
+/* Add firmware file, load and unload function |
+ * to download the firmware to target RAM |
+ */ |
+static struct fw_cb_config btusb_fwcbs[] = { |
+ { |
+ .fwfile = "ath3k-1.fw", |
+ .usb_id_table = ath_table, |
+ .fwload = ath_fw_load, |
+ .fwunload = ath_fw_unload |
+ }, |
+ {} |
+}; |
+ |
static struct usb_device_id btusb_table[] = { |
/* Generic Bluetooth USB device */ |
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, |
@@ -863,6 +884,7 @@ static int btusb_probe(struct usb_interface *intf, |
struct btusb_data *data; |
struct hci_dev *hdev; |
int i, err; |
+ const struct usb_device_id *match; |
BT_DBG("intf %p id %p", intf, id); |
@@ -922,6 +944,19 @@ static int btusb_probe(struct usb_interface *intf, |
data->udev = interface_to_usbdev(intf); |
data->intf = intf; |
+ for (i = 0; btusb_fwcbs[i].fwfile; i++) { |
+ match = usb_match_id(intf, btusb_fwcbs[i].usb_id_table); |
+ if (match) { |
+ if (btusb_fwcbs[i].fwload) { |
+ btusb_fwcbs[i].data = |
+ btusb_fwcbs[i].fwload(intf, |
+ btusb_fwcbs[i].fwfile, |
+ &btusb_fwcbs[i].bsuspend); |
+ } |
+ break; |
+ } |
+ } |
+ |
spin_lock_init(&data->lock); |
INIT_WORK(&data->work, btusb_work); |
@@ -1030,12 +1065,26 @@ static void btusb_disconnect(struct usb_interface *intf) |
{ |
struct btusb_data *data = usb_get_intfdata(intf); |
struct hci_dev *hdev; |
+ const struct usb_device_id *match; |
+ int i; |
BT_DBG("intf %p", intf); |
if (!data) |
return; |
+ for (i = 0; btusb_fwcbs[i].fwfile; i++) { |
+ match = usb_match_id(intf, btusb_fwcbs[i].usb_id_table); |
+ if (match) { |
+ if (btusb_fwcbs[i].fwunload) { |
+ btusb_fwcbs[i].fwunload(btusb_fwcbs[i].data, |
+ btusb_fwcbs[i].bsuspend); |
+ btusb_fwcbs[i].data = NULL; |
+ } |
+ break; |
+ } |
+ } |
+ |
hdev = data->hdev; |
__hci_dev_hold(hdev); |
@@ -1061,12 +1110,22 @@ static void btusb_disconnect(struct usb_interface *intf) |
static int btusb_suspend(struct usb_interface *intf, pm_message_t message) |
{ |
struct btusb_data *data = usb_get_intfdata(intf); |
+ const struct usb_device_id *match; |
+ int i; |
BT_DBG("intf %p", intf); |
if (data->suspend_count++) |
return 0; |
+ for (i = 0; btusb_fwcbs[i].fwfile; i++) { |
+ match = usb_match_id(intf, btusb_fwcbs[i].usb_id_table); |
+ if (match) { |
+ btusb_fwcbs[i].bsuspend = 1; |
+ break; |
+ } |
+ } |
+ |
spin_lock_irq(&data->txlock); |
if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) { |
set_bit(BTUSB_SUSPENDING, &data->flags); |
@@ -1179,6 +1238,14 @@ static int __init btusb_init(void) |
static void __exit btusb_exit(void) |
{ |
+ int i; |
+ for (i = 0; btusb_fwcbs[i].fwfile; i++) { |
+ if (btusb_fwcbs[i].fwunload && btusb_fwcbs[i].data) { |
+ btusb_fwcbs[i].fwunload(btusb_fwcbs[i].data, |
+ btusb_fwcbs[i].bsuspend); |
+ btusb_fwcbs[i].data = NULL; |
+ } |
+ } |
usb_deregister(&btusb_driver); |
} |