linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Bluetooth:ath3k&btusb: Add support for Qualcomm Atheros 3006 composite device
@ 2011-11-08  3:13 Yao, Costa
  2011-11-08  6:16 ` Marcel Holtmann
  0 siblings, 1 reply; 2+ messages in thread
From: Yao, Costa @ 2011-11-08  3:13 UTC (permalink / raw)
  To: marcel@holtmann.org, padovan@profusion.mobi,
	linux-bluetooth@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 9043 bytes --]

>From 312e18c8c46527cb7213fa57afc32094cdc9459c Mon Sep 17 00:00:00 2001
From: Costa yao <cqyao@qca.qualcomm.com>
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 <cqyao@qca.qualcomm.com>
---
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

[-- Attachment #2: Type: text/html, Size: 35791 bytes --]

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-11-08  6:16 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-08  3:13 [PATCH] Bluetooth:ath3k&btusb: Add support for Qualcomm Atheros 3006 composite device Yao, Costa
2011-11-08  6:16 ` Marcel Holtmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).