From patchwork Wed Sep 4 17:42:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wen-chien Jesse Sung X-Patchwork-Id: 272684 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 620592C0079 for ; Thu, 5 Sep 2013 03:43:08 +1000 (EST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1VHH6X-000178-5m; Wed, 04 Sep 2013 17:42:57 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1VHH6S-00016U-CP for kernel-team@lists.ubuntu.com; Wed, 04 Sep 2013 17:42:52 +0000 Received: from 112-104-99-96.adsl.dynamic.seed.net.tw ([112.104.99.96] helo=espresso.voip.idv.tw) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1VHH6R-0003Hu-O8; Wed, 04 Sep 2013 17:42:52 +0000 From: Jesse Sung To: kernel-team@lists.ubuntu.com Subject: [Raring][PATCH] UBUNTU: SAUCE: Bluetooth: use hci_send_cmd instead of usb_control_msg Date: Thu, 5 Sep 2013 01:42:29 +0800 Message-Id: <1378316549-26472-1-git-send-email-jesse.sung@canonical.com> X-Mailer: git-send-email 1.8.3.2 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: kernel-team-bounces@lists.ubuntu.com From: Wen-chien Jesse Sung BugLink: https://launchpad.net/bugs/1065400 Calling usb_control_msg directly to send firmware file does not work with new platforms. Use hci_send_cmd instead. Signed-off-by: Wen-chien Jesse Sung --- drivers/bluetooth/btusb.c | 58 +++++++++++++++++++++++------------------------ net/bluetooth/hci_core.c | 1 + 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 5be9002..3a82e09 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -49,7 +49,7 @@ static struct usb_driver btusb_driver; #define BTUSB_BROKEN_ISOC 0x20 #define BTUSB_WRONG_SCO_MTU 0x40 #define BTUSB_ATH3012 0x80 -#define BTUSB_BCM_PATCHRAM 0x100 +#define BTUSB_BCM_PATCHRAM 0x800 static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -226,14 +226,13 @@ static struct usb_device_id blacklist_table[] = { #define BTUSB_ISOC_RUNNING 2 #define BTUSB_SUSPENDING 3 #define BTUSB_DID_ISO_RESUME 4 -#define BTUSB_FIRMWARE_DONE 5 +#define BTUSB_FIRMWARE_DONE 7 struct btusb_data { struct hci_dev *hdev; struct usb_device *udev; struct usb_interface *intf; struct usb_interface *isoc; - const struct usb_device_id *id; spinlock_t lock; @@ -938,24 +937,20 @@ static void btusb_waker(struct work_struct *work) usb_autopm_put_interface(data->intf); } -#define PATCHRAM_TIMEOUT 1000 #define PATCHRAM_NAME_LEN 20 +#define PATCHRAM_BUF_SIZE (256 + 4) static void btusb_load_firmware(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct usb_device *udev = data->udev; - const struct usb_device_id *id = data->id; size_t pos = 0; int err = 0; char filename[PATCHRAM_NAME_LEN]; const struct firmware *fw; + u8 *buf = NULL; + u8 val = 0; - unsigned char reset_cmd[] = { 0x03, 0x0c, 0x00 }; - unsigned char download_cmd[] = { 0x2e, 0xfc, 0x00 }; - - if (!(id->driver_info & BTUSB_BCM_PATCHRAM)) - return; if (test_and_set_bit(BTUSB_FIRMWARE_DONE, &data->flags)) return; @@ -967,40 +962,43 @@ static void btusb_load_firmware(struct hci_dev *hdev) return; } - if (usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, USB_TYPE_CLASS, 0, 0, - reset_cmd, sizeof(reset_cmd), PATCHRAM_TIMEOUT) < 0) { - err = -1; + buf = kmalloc(PATCHRAM_BUF_SIZE, GFP_KERNEL); + if (!buf) goto out; - } - msleep(300); - if (usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, USB_TYPE_CLASS, 0, 0, - download_cmd, sizeof(download_cmd), PATCHRAM_TIMEOUT) < 0) { - err = -1; + err= hci_send_cmd(hdev, 0x0c03, 1, &val); + if (err) goto out; - } msleep(300); + err = hci_send_cmd(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) || - (usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, - USB_TYPE_CLASS, 0, 0, (void *)fw->data + pos, len, - PATCHRAM_TIMEOUT) < 0)) { - err = -1; + if (pos + len > fw->size) { + err = -EINVAL; goto out; } + memcpy(buf, fw->data + pos, len); + err = hci_send_cmd(hdev, le16_to_cpu(*(u16*)buf), + *(buf + sizeof(u16)), buf + sizeof(u16) + 1); + if (err) + goto out; pos += len; } - err = (usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, USB_TYPE_CLASS, 0, 0, - reset_cmd, sizeof(reset_cmd), PATCHRAM_TIMEOUT) < 0); + err= hci_send_cmd(hdev, 0x0c03, 1, &val); out: if (err) - BT_INFO("fail to load firmware, may not work correctly"); + BT_INFO("fail to load firmware"); else BT_INFO("firmware loaded"); + if (buf) + kfree(buf); release_firmware(fw); } @@ -1089,8 +1087,6 @@ static int btusb_probe(struct usb_interface *intf, init_usb_anchor(&data->isoc_anchor); init_usb_anchor(&data->deferred); - data->id = id; - hdev = hci_alloc_dev(); if (!hdev) return -ENOMEM; @@ -1107,7 +1103,9 @@ static int btusb_probe(struct usb_interface *intf, hdev->flush = btusb_flush; hdev->send = btusb_send_frame; hdev->notify = btusb_notify; - hdev->load_firmware = btusb_load_firmware; + + if (id->driver_info & BTUSB_BCM_PATCHRAM) + hdev->load_firmware = btusb_load_firmware; /* Interface numbers are hardcoded in the specification */ data->isoc = usb_ifnum_to_if(data->udev, 1); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 843f46f..927e55e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2193,6 +2193,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) return 0; } +EXPORT_SYMBOL(hci_send_cmd); /* Get data from the previously sent command */ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)