2011-11-08 03:13:00

by Yao, Costa

[permalink] [raw]
Subject: [PATCH] Bluetooth:ath3k&btusb: Add support for Qualcomm Atheros 3006 composite device

>From 312e18c8c46527cb7213fa57afc32094cdc9459c Mon Sep 17 00:00:00 2001
From: Costa yao <[email protected]>
Date: Thu, 3 Nov 2011 14:45:33 +0800


AR3006 is a composite device, and interface 0 is used for hid function, not bluetooth function.
So, we should make the following changes:
1 Blacklist AR3006 PID/VID in btusb and ath3k to load patch and sysconfig files
2 Add composite_device_table in btusb.c and ath3k_composite_device_table in ath3k.c
to check whether it is bluetooth interface
3 interface 3 is used for data->isoc

Signed-off-by: Costa yao <[email protected]>
---
drivers/bluetooth/ath3k.c | 67 +++++++++++++++++++++++++++++++++++++++++++--
drivers/bluetooth/btusb.c | 36 +++++++++++++++++++++++-
2 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 1622772..5c877c7 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -40,6 +40,7 @@

#define ATH3K_MODE_MASK 0x3F
#define ATH3K_NORMAL_MODE 0x0E
+#define ATH3K_PREBOOT_MODE 0x0D

#define ATH3K_PATCH_UPDATE 0x80
#define ATH3K_SYSCFG_UPDATE 0x40
@@ -71,6 +72,7 @@ static struct usb_device_id ath3k_table[] = {

/* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x3004) },
+ { USB_DEVICE(0x0CF3, 0x3006) },

/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) },
@@ -81,16 +83,26 @@ static struct usb_device_id ath3k_table[] = {
MODULE_DEVICE_TABLE(usb, ath3k_table);

#define BTUSB_ATH3012 0x80
+#define BTUSB_ATH3006 0x0100
/* This table is to load patch and sysconfig files
* for AR3012 */
static struct usb_device_id ath3k_blist_tbl[] = {

/* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x3006), .driver_info = BTUSB_ATH3006 },

{ } /* Terminating entry */
};

+/* Atheros composite devices table
+ */
+static struct usb_device_id ath3k_composite_device_table[] = {
+
+ { USB_DEVICE(0x0cf3, 0x3006) },
+
+ { } /* Terminating entry */
+};
#define USB_REQ_DFU_DNLOAD 1
#define BULK_SIZE 4096
#define FW_HDR_SIZE 20
@@ -361,11 +373,20 @@ static int ath3k_probe(struct usb_interface *intf,
const struct firmware *firmware;
struct usb_device *udev = interface_to_usbdev(intf);
int ret;
+ unsigned char fw_state;
+ const struct usb_device_id *match_comp_dev;

BT_DBG("intf %p id %p", intf, id);
-
- if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
- return -ENODEV;
+ /* For composite device */
+ match_comp_dev = usb_match_id(intf, ath3k_composite_device_table);
+ if (match_comp_dev)
+ {
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 2)
+ return -ENODEV;
+ }else {
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+ return -ENODEV;
+ }

/* match device ID in ath3k blacklist table */
if (!id->driver_info) {
@@ -399,6 +420,46 @@ static int ath3k_probe(struct usb_interface *intf,
}
ath3k_switch_pid(udev);
return 0;
+ } else if (id->driver_info & BTUSB_ATH3006) {
+
+ if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001)
+ {
+ BT_ERR("ath3k_probe: udev->descriptor.bcdDevice");
+ return -ENODEV;
+ }
+ ret = ath3k_get_state(udev, &fw_state);
+ if (ret < 0) {
+ BT_ERR("ath3k_probe: ath3k_get_state err");
+ return ret;
+ }
+ if ((fw_state & ATH3K_MODE_MASK) == ATH3K_PREBOOT_MODE) {
+ BT_ERR("ath3k_probe: firmware are in preboot mode now");
+ BT_ERR("ath3k_probe: try to switch to Normal Mode");
+ ret = ath3k_set_normal_mode(udev);
+ if (ret <0) {
+ BT_ERR("ath3k_probe: set normal mode failed");
+ return ret;
+ }
+ }
+ /*Note we should wait for a while*/
+ mdelay(100);
+ ret = ath3k_load_patch(udev);
+ if (ret < 0) {
+ BT_ERR("ath3k_probe: Load patch file failed");
+ return ret;
+ }
+ ret = ath3k_load_syscfg(udev);
+ if (ret < 0) {
+ BT_ERR("ath3k_probe: Load sysconfig file failed");
+ return ret;
+ }
+ ret = ath3k_switch_pid(udev);
+ if (ret < 0) {
+ BT_ERR("ath3k_probe: switch pid failed");
+ return ret;
+ }
+
+ return 0;
}

ret = request_firmware(&firmware, ATH3K_FIRMWARE, &udev->dev);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index abfc4ee..47e8498 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -55,6 +55,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_BROKEN_ISOC 0x20
#define BTUSB_WRONG_SCO_MTU 0x40
#define BTUSB_ATH3012 0x80
+#define BTUSB_ATH3006 0x0100

static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -100,6 +101,9 @@ static struct usb_device_id btusb_table[] = {
/* Canyon CN-BTU1 with HID interfaces */
{ USB_DEVICE(0x0c10, 0x0000) },

+ /* Qualcomm atheros with HID interfaces */
+ { USB_DEVICE(0x0cf3, 0x3006) },
+
{ } /* Terminating entry */
};

@@ -122,6 +126,7 @@ static struct usb_device_id blacklist_table[] = {

/* Atheros 3012 with sflash firmware */
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x3006), .driver_info = BTUSB_ATH3006 },

/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -179,6 +184,18 @@ static struct usb_device_id blacklist_table[] = {
{ } /* Terminating entry */
};

+/*
+ * For composite device, interface 0 may be not for bluetooth function.
+ * It is better to let the vendor code to handle this situation.
+ * So, We use composite_device_table to record the composite devices.
+ */
+static struct usb_device_id composite_device_table[] = {
+ /* Qualcomm Atheros composite device 3006 */
+ { USB_DEVICE(0x0cf3, 0x3006) },
+
+ { } /* Terminating entry */
+};
+
#define BTUSB_MAX_ISOC_FRAMES 10

#define BTUSB_INTR_RUNNING 0
@@ -909,13 +926,25 @@ 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_comp_dev;

BT_DBG("intf %p id %p", intf, id);
+ /* For composite device
+ * it may not the case that interface 0 is for bluetooth function.
+ */
+ match_comp_dev = usb_match_id(intf, composite_device_table);
+ if (match_comp_dev)
+ {
+ if (intf->cur_altsetting->desc.bInterfaceNumber != 2)
+ return -ENODEV;
+ goto match_id;
+ }

/* interface numbers are hardcoded in the spec */
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
return -ENODEV;

+match_id:
if (!id->driver_info) {
const struct usb_device_id *match;
match = usb_match_id(intf, blacklist_table);
@@ -935,7 +964,7 @@ static int btusb_probe(struct usb_interface *intf,
if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
return -ENODEV;

- if (id->driver_info & BTUSB_ATH3012) {
+ if ((id->driver_info & BTUSB_ATH3012) || (id->driver_info & BTUSB_ATH3006)) {
struct usb_device *udev = interface_to_usbdev(intf);

/* Old firmware would otherwise let ath3k driver load
@@ -1059,6 +1088,11 @@ static int btusb_probe(struct usb_interface *intf,
}
}

+ if (id->driver_info & BTUSB_ATH3006) {
+ BT_ERR("hardcoded: Interface 3");
+ data->isoc = usb_ifnum_to_if(data->udev, 3);
+ }
+
if (data->isoc) {
err = usb_driver_claim_interface(&btusb_driver,
data->isoc, data);
--
1.7.4.1


2011-11-08 06:16:03

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH] Bluetooth:ath3k&btusb: Add support for Qualcomm Atheros 3006 composite device

Hi Costa,

> From 312e18c8c46527cb7213fa57afc32094cdc9459c Mon Sep 17 00:00:00 2001
> From: Costa yao <[email protected]>
> Date: Thu, 3 Nov 2011 14:45:33 +0800
>
>
> AR3006 is a composite device, and interface 0 is used for hid function, not bluetooth function.
> So, we should make the following changes:
> 1 Blacklist AR3006 PID/VID in btusb and ath3k to load patch and sysconfig files
> 2 Add composite_device_table in btusb.c and ath3k_composite_device_table in ath3k.c
> to check whether it is bluetooth interface
> 3 interface 3 is used for data->isoc

please send proper formatted patch. This one is all messed up and I am
not even trying to review it.

Also split this at least into 2 patches, one for btusb.c and one for the
ath3k.c changes.

Regards

Marcel