Return-Path: From: "Yao, Costa" To: "marcel@holtmann.org" , "padovan@profusion.mobi" , "linux-bluetooth@vger.kernel.org" Subject: [PATCH] Bluetooth:ath3k&btusb: Add support for Qualcomm Atheros 3006 composite device Date: Tue, 8 Nov 2011 03:13:00 +0000 Message-ID: <07BBB2AAB1A10A488A2AD166C7CB8B0DEE9C62@nasanexd02b.na.qualcomm.com> Content-Type: multipart/alternative; boundary="_000_07BBB2AAB1A10A488A2AD166C7CB8B0DEE9C62nasanexd02bnaqual_" MIME-Version: 1.0 List-ID: --_000_07BBB2AAB1A10A488A2AD166C7CB8B0DEE9C62nasanexd02bnaqual_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable >From 312e18c8c46527cb7213fa57afc32094cdc9459c Mon Sep 17 00:00:00 2001 From: Costa yao 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 i= n ath3k.c to check whether it is bluetooth interface 3 interface 3 is used for data->isoc Signed-off-by: Costa yao --- 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[] =3D { /* 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[] =3D { 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[] =3D { /* Atheros AR3012 with sflash firmware*/ { USB_DEVICE(0x0cf3, 0x3004), .driver_info =3D BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3006), .driver_info =3D BTUSB_ATH3006 }, { } /* Terminating entry */ }; +/* Atheros composite devices table + */ +static struct usb_device_id ath3k_composite_device_table[] =3D { + + { 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 =3D 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 !=3D 0) - return -ENODEV; + /* For composite device */ + match_comp_dev =3D usb_match_id(intf, ath3k_composite_device_table)= ; + if (match_comp_dev) + { + if (intf->cur_altsetting->desc.bInterfaceNumber !=3D 2) + return -ENODEV; + }else { + if (intf->cur_altsetting->desc.bInterfaceNumber !=3D 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 =3D 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) =3D=3D ATH3K_PREBOOT_MODE) = { + BT_ERR("ath3k_probe: firmware are in preboot mod= e now"); + BT_ERR("ath3k_probe: try to switch to Normal Mod= e"); + ret =3D 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 =3D ath3k_load_patch(udev); + if (ret < 0) { + BT_ERR("ath3k_probe: Load patch file failed"); + return ret; + } + ret =3D ath3k_load_syscfg(udev); + if (ret < 0) { + BT_ERR("ath3k_probe: Load sysconfig file failed"= ); + return ret; + } + ret =3D ath3k_switch_pid(udev); + if (ret < 0) { + BT_ERR("ath3k_probe: switch pid failed"); + return ret; + } + + return 0; } ret =3D 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[] =3D { /* Generic Bluetooth USB device */ @@ -100,6 +101,9 @@ static struct usb_device_id btusb_table[] =3D { /* 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[] =3D { /* Atheros 3012 with sflash firmware */ { USB_DEVICE(0x0cf3, 0x3004), .driver_info =3D BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3006), .driver_info =3D BTUSB_ATH3006 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info =3D BTUSB_IGNORE }, @@ -179,6 +184,18 @@ static struct usb_device_id blacklist_table[] =3D { { } /* 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[] =3D { + /* 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 =3D usb_match_id(intf, composite_device_table); + if (match_comp_dev) + { + if (intf->cur_altsetting->desc.bInterfaceNumber !=3D 2) + return -ENODEV; + goto match_id; + } /* interface numbers are hardcoded in the spec */ if (intf->cur_altsetting->desc.bInterfaceNumber !=3D 0) return -ENODEV; +match_id: if (!id->driver_info) { const struct usb_device_id *match; match =3D 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_A= TH3006)) { struct usb_device *udev =3D 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 =3D usb_ifnum_to_if(data->udev, 3); + } + if (data->isoc) { err =3D usb_driver_claim_interface(&btusb_driver, data->isoc, = data); -- 1.7.4.1 --_000_07BBB2AAB1A10A488A2AD166C7CB8B0DEE9C62nasanexd02bnaqual_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

From 312e18c8c46527cb7213fa57af= c32094cdc9459c Mon Sep 17 00:00:00 2001

From: Costa yao <cqyao@qca.qualcomm.com>

Date: Thu, 3 Nov 2011 14:45:33 = +0800

&n= bsp;

&n= bsp;

AR3006 is a composite device, a= nd interface 0 is used for hid function, not bluetooth function.=

So, we should make the followin= g changes:

1  Blacklist AR3006 PID/VI= D in btusb and ath3k to load patch and sysconfig files

2  Add composite_device_ta= ble in btusb.c and ath3k_composite_device_table in ath3k.c

    to check whe= ther it is bluetooth interface

3  interface 3 is used for= data->isoc

&n= bsp;

Signed-off-by: Costa yao <cqyao@qca.qualcomm.com>=

---

drivers/bluetooth/ath3k.c |&nbs= p;  67 ++++++++++++= 3;++++++++++++++= 3;++++++++++++++= 3;--

drivers/bluetooth/btusb.c |&nbs= p;  36 ++++++++++++= 3;++++++++++-

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/bluet= ooth/ath3k.c

@@ -40,6 +40,7 @@

 

#d= efine ATH3K_MODE_MASK         =             &nb= sp;            =   0x3F

#d= efine ATH3K_NORMAL_MODE        &nbs= p;           0x0E

+#define ATH3K_PREBOOT_MODE=             &nb= sp;            =    0x0D

 

#d= efine ATH3K_PATCH_UPDATE        &nb= sp;            = 0x80

#d= efine ATH3K_SYSCFG_UPDATE        &n= bsp;           0x40<= /o:p>

@@ -71,6 +72,7 @@ static st= ruct usb_device_id ath3k_table[] =3D {

 

     &= nbsp;  /* Atheros AR3012 with sflash firmware*/

     &= nbsp; { USB_DEVICE(0x0CF3, 0x3004) },

+     {= USB_DEVICE(0x0CF3, 0x3006) },

 

     &= nbsp;  /* Atheros AR5BBU12 with sflash firmware */

     &= nbsp; { USB_DEVICE(0x0489, 0xE02C) },

@@ -81,16 +83,26 @@ static = struct usb_device_id ath3k_table[] =3D {

MODULE_DEVICE_TABLE(usb, ath3k_= table);

 

#d= efine BTUSB_ATH3012         &n= bsp;      0x80

+#define BTUSB_ATH3006 = ;            &n= bsp;  0x0100

/* This table is to load patch = and sysconfig files

  * for AR3012 */

static struct usb_device_id ath= 3k_blist_tbl[] =3D {

 

     &= nbsp;  /* Atheros AR3012 with sflash firmware*/

     &= nbsp; { USB_DEVICE(0x0cf3, 0x3004), .driver_info =3D BTUSB_ATH3012 },<= /o:p>

+     {= USB_DEVICE(0x0cf3, 0x3006), .driver_info =3D BTUSB_ATH3006 },

 

     &= nbsp;  { }      /* Terminating entry */<= /o:p>

};

 

+/* Atheros composite devic= es table

+ */

+static struct usb_device_i= d ath3k_composite_device_table[] =3D {

+

+    &n= bsp;  { USB_DEVICE(0x0cf3, 0x3006) },

+

+    &n= bsp;  { }      /* Terminating entry */

+};

#define USB_REQ_DFU_DNLOAD 1

#define BULK_SIZE  &n= bsp;            = ;   4096

#define FW_HDR_SIZE  =          20

@@ -361,11 +373,20 @@ stati= c int ath3k_probe(struct usb_interface *intf,

     &= nbsp; const struct firmware *firmware;

     &= nbsp; struct usb_device *udev =3D interface_to_usbdev(intf);

     &= nbsp; int ret;

+      = unsigned char fw_state;

+      = const struct usb_device_id *match_comp_dev;

 

     &= nbsp;  BT_DBG("intf %p id %p", intf, id);<= /p>

-

-     =    if (intf->cur_altsetting->desc.bInterfaceNumber !=3D 0)<= o:p>

-     =             return -= ENODEV;

+    /* For = composite device */

+    &n= bsp;  match_comp_dev =3D usb_match_id(intf, ath3k_composite_device_tab= le);

+    &n= bsp;  if (match_comp_dev)

+      = {

+     &= nbsp;         if (intf->cur_alts= etting->desc.bInterfaceNumber !=3D 2)

+     &= nbsp;           &nbs= p;      return -ENODEV;

+      = }else {

+     &= nbsp;         if (intf->cur_alts= etting->desc.bInterfaceNumber !=3D 0)

+     &= nbsp;           &nbs= p;      return -ENODEV;

+      = }

 

     &= nbsp;  /* match device ID in ath3k blacklist table */

     &= nbsp; if (!id->driver_info) {

@@ -399,6 +420,46 @@ static= int ath3k_probe(struct usb_interface *intf,

     &= nbsp;          }

     &= nbsp;          ath3k_switch_pi= d(udev);

     &= nbsp;          return 0;<= /o:p>

+    &n= bsp;  } else if (id->driver_info & BTUSB_ATH3006) {<= /span>

+

+    &n= bsp;           if (le16_t= o_cpu(udev->descriptor.bcdDevice) > 0x0001)

+     &= nbsp;         {

+     &= nbsp;           &nbs= p;      BT_ERR("ath3k_probe: udev->descrip= tor.bcdDevice");

+    &n= bsp;            = ;         return -ENODEV;

+     &= nbsp;         }

+     &= nbsp;         ret =3D ath3k_get_sta= te(udev, &fw_state);

+    &n= bsp;           if (ret &l= t; 0) {

+     &= nbsp;           &nbs= p;      BT_ERR("ath3k_probe: ath3k_get_state = err");

+    &n= bsp;            = ;         return ret;

+     &= nbsp;         }

+     &= nbsp;        if ((fw_state & ATH3K_M= ODE_MASK) =3D=3D ATH3K_PREBOOT_MODE) {

+    &n= bsp;            = ;         BT_ERR("ath3k_probe:= firmware are in preboot mode now");

+    &n= bsp;            = ;         BT_ERR("ath3k_probe:= try to switch to Normal Mode");

+     &= nbsp;            &nb= sp;     ret =3D ath3k_set_normal_mode(udev);=

+     &= nbsp;           &nbs= p;      if (ret <0) {

+     &= nbsp;            &nb= sp;            BT_ER= R("ath3k_probe: set normal mode failed");

+     &= nbsp;            &nb= sp;            retur= n ret;

+     &= nbsp;           &nbs= p;     }

+     &= nbsp;        }

+     &= nbsp;           &nbs= p;    /*Note we should wait for a while*/<= /p>

+     &= nbsp;           &nbs= p;    mdelay(100);

+    &n= bsp;           ret =3D at= h3k_load_patch(udev);

+    &n= bsp;           if (ret &l= t; 0) {

+    &n= bsp;            = ;         BT_ERR("ath3k_probe:= Load patch file failed");

+    &n= bsp;            = ;         return ret;

+    &n= bsp;           }

+    &n= bsp;           ret =3D at= h3k_load_syscfg(udev);

+    &n= bsp;           if (ret &l= t; 0) {

+    &n= bsp;            = ;         BT_ERR("ath3k_probe:= Load sysconfig file failed");

+    &n= bsp;            = ;         return ret;

+    &n= bsp;           }

+    &n= bsp;           ret =3D at= h3k_switch_pid(udev);

+    &n= bsp;           if (ret &l= t; 0) {

+    &n= bsp;            = ;         BT_ERR("ath3k_probe:= switch pid failed");

+    &n= bsp;            = ;         return ret;

+    &n= bsp;           }

+    &n= bsp;          

+    &n= bsp;           return 0;<= o:p>

     &= nbsp; }

 

     &= nbsp;  ret =3D request_firmware(&firmware, ATH3K_FIRMWARE, &ud= ev->dev);

diff --git a/drivers/bluetooth/= btusb.c b/drivers/bluetooth/btusb.c

index abfc4ee..47e8498 100644

--- a/drivers/bluetooth/btusb.c=

+++ b/drivers/bluet= ooth/btusb.c

@@ -55,6 +55,7 @@ static st= ruct usb_driver btusb_driver;

#define BTUSB_BROKEN_ISOC =      0x20

#define BTUSB_WRONG_SCO_MTU&nbs= p;    0x40

#define BTUSB_ATH3012 &nbs= p;            &= nbsp; 0x80

+#define BTUSB_ATH3006 = ;            &n= bsp;  0x0100

 

 static struct usb_device_= id btusb_table[] =3D {

     &= nbsp; /* Generic Bluetooth USB device */

@@ -100,6 +101,9 @@ static = struct usb_device_id btusb_table[] =3D {

     &= nbsp; /* Canyon CN-BTU1 with HID interfaces */

     &= nbsp; { USB_DEVICE(0x0c10, 0x0000) },

 

+    &n= bsp;  /* Qualcomm atheros with HID interfaces */

+    &n= bsp;  { USB_DEVICE(0x0cf3, 0x3006) },

+

     &= nbsp; { }      /* Terminating entry */<= /span>

};

 

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

 

     &= nbsp;  /* Atheros 3012 with sflash firmware */

     &= nbsp; { USB_DEVICE(0x0cf3, 0x3004), .driver_info =3D BTUSB_ATH3012 },<= /o:p>

+    &n= bsp;  { USB_DEVICE(0x0cf3, 0x3006), .driver_info =3D BTUSB_ATH3006 },<= o:p>

 

     &= nbsp;  /* Atheros AR5BBU12 with sflash firmware */

     &= nbsp; { USB_DEVICE(0x0489, 0xe02c), .driver_info =3D BTUSB_IGNORE },

@@ -179,6 +184,18 @@ static= struct usb_device_id blacklist_table[] =3D {

     &= nbsp; { }      /* Terminating entry */<= /span>

};

 

+/*

+ * For composite device, i= nterface 0 may be not for bluetooth function.

+ * It is better to let the= vendor code to handle this situation.

+ * So, We use composite_de= vice_table to record the composite devices.

+ */

+static struct usb_device_i= d composite_device_table[] =3D {

+    &n= bsp;  /* Qualcomm Atheros composite device 3006 */

+    &n= bsp;  { USB_DEVICE(0x0cf3, 0x3006) },

+

+    &n= bsp;  { }      /* Terminating entry */

+};

+

#define BTUSB_MAX_ISOC_FRAMES&n= bsp;   10

 

 #define BTUSB_INTR_RUNNIN= G  0

@@ -909,13 +926,25 @@ stati= c int btusb_probe(struct usb_interface *intf,

     &= nbsp; struct btusb_data *data;

     &= nbsp; struct hci_dev *hdev;

     &= nbsp; int i, err;

+    &n= bsp;  const struct usb_device_id *match_comp_dev;

 

     &= nbsp;  BT_DBG("intf %p id %p", intf, id);<= /p>

+      = /* For composite device

+     * it m= ay not the case that interface 0 is for bluetooth function.

+     */

+    &n= bsp;  match_comp_dev =3D usb_match_id(intf, composite_device_table);

+    &n= bsp;  if (match_comp_dev)

+    &n= bsp;  {

+    &n= bsp;         if (intf->cur_altsetting= ->desc.bInterfaceNumber !=3D 2)

+    &n= bsp;            &nbs= p;     return -ENODEV;

+    &n= bsp;         goto match_id;

+    &n= bsp;  }

 

     &= nbsp;  /* interface numbers are hardcoded in the spec */

     &= nbsp; if (intf->cur_altsetting->desc.bInterfaceNumber !=3D 0)

     &= nbsp;          return -ENODEV;=

 

+match_id:

     &= nbsp; if (!id->driver_info) {

     &= nbsp;          const struct us= b_device_id *match;

     &= nbsp;          match =3D usb_m= atch_id(intf, blacklist_table);

@@ -935,7 +964,7 @@ static = int btusb_probe(struct usb_interface *intf,

     &= nbsp; if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)=

     &= nbsp;          return -ENODEV;=

 

-     =    if (id->driver_info & BTUSB_ATH3012) {

+    &n= bsp;  if ((id->driver_info & BTUSB_ATH3012) || (id->driver_i= nfo & BTUSB_ATH3006)) {

     &= nbsp;          struct usb_devi= ce *udev =3D interface_to_usbdev(intf);

 

     &= nbsp;           /* Old fi= rmware would otherwise let ath3k driver load

@@ -1059,6 +1088,11 @@ stat= ic int btusb_probe(struct usb_interface *intf,

     &= nbsp;          }

     &= nbsp; }

 

+    &n= bsp;  if (id->driver_info & BTUSB_ATH3006) {<= /p>

+    &n= bsp;           BT_ERR(&qu= ot;hardcoded: Interface 3");

+    &n= bsp;           data->i= soc =3D usb_ifnum_to_if(data->udev, 3);

+    }<= /o:p>

+

     &= nbsp; if (data->isoc) {

     &= nbsp;          err =3D usb_dri= ver_claim_interface(&btusb_driver,

     &= nbsp;           &nbs= p;            &= nbsp;           &nbs= p;            &= nbsp;       data->isoc, data);<= /span>

--

1.7.4.1

--_000_07BBB2AAB1A10A488A2AD166C7CB8B0DEE9C62nasanexd02bnaqual_--