[Saucy][PATCH 1/5] UBUNTU: SAUCE: Bluetooth: Support for loading broadcom patchram firmware
Tim Gardner
tim.gardner at canonical.com
Fri Sep 6 13:56:33 UTC 2013
On 09/06/2013 05:07 AM, Wen-chien Jesse Sung wrote:
> BugLink: https://launchpad.net/bugs/1065400
>
> There is an user space firmware loading tool which can be found at
> http://marc.info/?l=linux-bluetooth&m=132039175324993&w=2
>
> The supported firmware is in hcd format, which is a collection of
> hci commands. The download process would be:
> 1. reset command
> 2. download command
> 3. firmware image in hcd file
> 4. reset command
>
> /sys/kernel/debug/usb/devices before loading firmware:
> T: Bus=01 Lev=02 Prnt=02 Port=04 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
> D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
> P: Vendor=0a5c ProdID=21d3 Rev= 1.12
> S: Manufacturer=Broadcom Corp
> S: Product=BCM43142A0
> S: SerialNumber=3859F9D6199A
> C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA
> I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
> E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
> E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
> E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
> I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
> E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
> I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
> E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
> I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
> E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
> I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
> E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
> I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
> E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
> I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
> E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
> I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
> E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
> E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
> I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
>
> /sys/kernel/debug/usb/devices after loading firmware:
> T: Bus=01 Lev=02 Prnt=02 Port=04 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
> D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
> P: Vendor=0a5c ProdID=21d3 Rev= 1.12
> S: Manufacturer=Broadcom Corp
> S: Product=BCM43142A0
> S: SerialNumber=3859F9D6199A
> C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA
> I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
> E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
> E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
> I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
> I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
> I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
> I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
> I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
> I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
> E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
> I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
> E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms
> E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms
> I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
>
> Signed-off-by: Wen-chien Jesse Sung <jesse.sung at canonical.com>
> ---
> drivers/bluetooth/btusb.c | 76 +++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 73 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 8e16f0a..09117b8 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -24,6 +24,7 @@
> #include <linux/module.h>
> #include <linux/usb.h>
> #include <linux/firmware.h>
> +#include <linux/delay.h>
>
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
> @@ -49,6 +50,7 @@ static struct usb_driver btusb_driver;
> #define BTUSB_WRONG_SCO_MTU 0x40
> #define BTUSB_ATH3012 0x80
> #define BTUSB_INTEL 0x100
> +#define BTUSB_BCM_PATCHRAM 0x800
>
> static struct usb_device_id btusb_table[] = {
> /* Generic Bluetooth USB device */
> @@ -104,13 +106,13 @@ static struct usb_device_id btusb_table[] = {
> { USB_DEVICE(0x0b05, 0x17b5) },
> { USB_DEVICE(0x04ca, 0x2003) },
> { USB_DEVICE(0x0489, 0xe042) },
> - { USB_DEVICE(0x413c, 0x8197) },
> + { USB_DEVICE(0x413c, 0x8197), .driver_info = BTUSB_BCM_PATCHRAM },
>
> /* Foxconn - Hon Hai */
> - { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
> + { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM },
>
> /*Broadcom devices with vendor specific id */
> - { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
> + { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM },
>
> { } /* Terminating entry */
> };
> @@ -1324,6 +1326,71 @@ exit_mfg_deactivate:
> return 0;
> }
>
> +static int btusb_setup_patchram_packet(struct hci_dev *hdev, u16 opcode, u32 plen, const void *param)
> +{
> + struct sk_buff *skb;
> +
> + skb = __hci_cmd_sync(hdev, opcode, plen, param, HCI_INIT_TIMEOUT);
> + if (IS_ERR(skb))
> + return PTR_ERR(skb);
> + kfree_skb(skb);
> + return 0;
> +}
> +
> +#define PATCHRAM_NAME_LEN 20
> +
> +static int btusb_setup_patchram(struct hci_dev *hdev)
> +{
> + struct btusb_data *data = hci_get_drvdata(hdev);
> + struct usb_device *udev = data->udev;
> + size_t pos = 0;
> + int err = 0;
> + char filename[PATCHRAM_NAME_LEN];
> + const struct firmware *fw;
> + u8 val = 0x00;
> +
> + snprintf(filename, PATCHRAM_NAME_LEN, "fw-%04x_%04x.hcd",
> + le16_to_cpu(udev->descriptor.idVendor),
> + le16_to_cpu(udev->descriptor.idProduct));
> + if (request_firmware(&fw, (const char *) filename, &udev->dev) < 0) {
> + BT_INFO("can't load firmware, may not work correctly");
> + return 0;
> + }
> +
> + err = btusb_setup_patchram_packet(hdev, 0x0c03, 1, &val);
> + if (err)
> + goto out;
> +
> + err = btusb_setup_patchram_packet(hdev, 0xfc2e, 1, &val);
> + if (err)
> + goto out;
> +
> + msleep(1000);
> + while (pos < fw->size) {
> + size_t len;
> + len = fw->data[pos + 2] + 3;
> + if (pos + len > fw->size) {
> + err = -EINVAL;
> + goto out;
> + }
> + err = btusb_setup_patchram_packet(hdev, le16_to_cpu(*(u16*)(fw->data + pos)),
> + fw->data[pos + 2] , &fw->data[pos + 3]);
> + if (err)
> + goto out;
> + pos += len;
> + }
> +
> + err = btusb_setup_patchram_packet(hdev, 0x0c03, 1, &val);
> +out:
> + release_firmware(fw);
> + if (err) {
> + BT_INFO("fail to load firmware");
> + return err;
> + }
> + BT_INFO("firmware loaded");
> + return 0;
> +}
> +
> static int btusb_probe(struct usb_interface *intf,
> const struct usb_device_id *id)
> {
> @@ -1432,6 +1499,9 @@ static int btusb_probe(struct usb_interface *intf,
> if (id->driver_info & BTUSB_INTEL)
> hdev->setup = btusb_setup_intel;
>
> + if (id->driver_info & BTUSB_BCM_PATCHRAM)
> + hdev->setup = btusb_setup_patchram;
> +
> /* Interface numbers are hardcoded in the specification */
> data->isoc = usb_ifnum_to_if(data->udev, 1);
>
>
Does this patch set suffer from the same 'use hci_send_cmd instead of
usb_control_msg' deficiency as was just proposed for Quantal/Raring ?
rtg
--
Tim Gardner tim.gardner at canonical.com
More information about the kernel-team
mailing list