All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] Bluetooth: btusb: Add BCM20702 firmware upgrade support
@ 2014-04-21 10:32 Jesse Sung
  2014-04-21 18:19 ` Marcel Holtmann
  0 siblings, 1 reply; 12+ messages in thread
From: Jesse Sung @ 2014-04-21 10:32 UTC (permalink / raw)
  To: Petri Gynther, Marcel Holtmann, linux-bluetooth
  Cc: Gustavo Padovan, Johan Hedberg

Hi Marcel,

Sorry for creating a new thread instead since I didn't subscribe this 
mailing list.

>>>> Interestingly, now that I look at that page more closely, Ubuntu 12.04
>>>> LTS with kernel 3.8 supports this already? Has Ubuntu made a patch
>>>> that bluetooth-next doesn't have?
>>>
>>> That is Ubuntu for you. They just push patches into their kernel and never give them back to upstream or make sure they get merged into bluetooth-next. I really dislike that behavior. It is always the easy way out instead of trying to do the right thing.
>>>
>>
>> See this page: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1065400
>
> It is a stupid userspace version that is racy as hell. Even the bug mentions that it should be done in the kernel. And I am pretty sure that was my initial comment as well. Just posting the userspace patch for reference.

No it's not the stupid userspace loader you're referring to.

And no, these patches are not pushed into Ubuntu kernel only.

These stupid patches were sent to this mailing list for review, for 
three or four times, and all of them were rejected by you. The latest 
version of patches that got rejected should be quite similar to Petri's.

Regards,
Jesse

^ permalink raw reply	[flat|nested] 12+ messages in thread
* [PATCH] Bluetooth: btusb: Add BCM20702 firmware upgrade support
@ 2014-04-09  1:05 Petri Gynther
  2014-04-09  1:36 ` Marcel Holtmann
  0 siblings, 1 reply; 12+ messages in thread
From: Petri Gynther @ 2014-04-09  1:05 UTC (permalink / raw)
  To: linux-bluetooth

After hardware reset, BCM20702 obtains its initial firmware from a PROM chip.
Once this initial firmware is running, the firmware can be further upgraded
over HCI interface with .hcd files provided by Broadcom. This is also known
as "patch RAM" support. This change implements that.

If the .hcd file is not found in /lib/firmware, BCM20702 continues to operate
with the initial firmware. Sample kernel log:
  hotplug: sys=firmware act=add fw=brcm/bcm20702-0a5c-22be.hcd dev=...
  Bluetooth: hci0: BCM20702: patch brcm/bcm20702-0a5c-22be.hcd not found
  Bluetooth: hci0: BCM20702: firmware hci_ver=06 hci_rev=1000 lmp_ver=06 lmp_subver=220e

If the .hcd file is found, btusb driver pushes it to BCM20702, and BCM20702
starts using the new firmware. Sample kernel log:
  hotplug: sys=firmware act=add fw=brcm/bcm20702-0a5c-22be.hcd dev=...
  Bluetooth: hci0: BCM20702: patching hci_ver=06 hci_rev=1000 lmp_ver=06 lmp_subver=220e
  Bluetooth: hci0: BCM20702: firmware hci_ver=06 hci_rev=1389 lmp_ver=06 lmp_subver=220e

Above, we can see that hci_rev goes from 1000 to 1389 as a result of the upgrade.

Signed-off-by: Petri Gynther <pgynther@google.com>
---
 drivers/bluetooth/btusb.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index f338b0c..371d7e9 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -49,6 +49,7 @@ static struct usb_driver btusb_driver;
 #define BTUSB_WRONG_SCO_MTU	0x40
 #define BTUSB_ATH3012		0x80
 #define BTUSB_INTEL		0x100
+#define BTUSB_BCM20702_PATCHRAM	0x200
 
 static const struct usb_device_id btusb_table[] = {
 	/* Generic Bluetooth USB device */
@@ -103,6 +104,7 @@ static const struct usb_device_id btusb_table[] = {
 	/* Broadcom BCM20702A0 */
 	{ USB_DEVICE(0x0489, 0xe042) },
 	{ USB_DEVICE(0x04ca, 0x2003) },
+	{ USB_DEVICE(0x0a5c, 0x22be), .driver_info = BTUSB_BCM20702_PATCHRAM },
 	{ USB_DEVICE(0x0b05, 0x17b5) },
 	{ USB_DEVICE(0x0b05, 0x17cb) },
 	{ USB_DEVICE(0x413c, 0x8197) },
@@ -1380,6 +1382,140 @@ exit_mfg_deactivate:
 	return 0;
 }
 
+static int btusb_setup_bcm20702(struct hci_dev *hdev)
+{
+	struct btusb_data *data = hci_get_drvdata(hdev);
+	struct usb_device *udev = data->udev;
+	char fw_name[64];
+	const struct firmware *fw;
+	const u8 *fw_ptr;
+	size_t fw_size;
+	const struct hci_command_hdr *cmd;
+	const u8 *cmd_param;
+	u16 opcode;
+	struct sk_buff *skb;
+	struct hci_rp_read_local_version *ver;
+	long ret;
+
+	snprintf(fw_name, sizeof(fw_name), "brcm/bcm20702-%04x-%04x.hcd",
+		 le16_to_cpu(udev->descriptor.idVendor),
+		 le16_to_cpu(udev->descriptor.idProduct));
+
+	ret = request_firmware(&fw, fw_name, &hdev->dev);
+	if (ret < 0) {
+		BT_INFO("%s: BCM20702: patch %s not found", hdev->name,
+			fw_name);
+		ret = 0;
+		goto get_fw_ver;
+	}
+
+	/* Reset */
+	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret);
+		goto reset_fw;
+	}
+	kfree_skb(skb);
+
+	/* Read Local Version Info */
+	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
+			     HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
+			hdev->name, ret);
+		goto reset_fw;
+	}
+
+	ver = (struct hci_rp_read_local_version *) skb->data;
+	BT_INFO("%s: BCM20702: patching hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
+		"lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev,
+		ver->lmp_ver, ver->lmp_subver);
+	kfree_skb(skb);
+
+	/* Start Download */
+	skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: BCM20702: Download Minidrv command failed (%ld)",
+			hdev->name, ret);
+		goto reset_fw;
+	}
+	kfree_skb(skb);
+
+	/* 50 msec delay after Download Minidrv completes */
+	msleep(50);
+
+	fw_ptr = fw->data;
+	fw_size = fw->size;
+
+	while (fw_size >= sizeof(*cmd)) {
+		cmd = (struct hci_command_hdr *) fw_ptr;
+		fw_ptr += sizeof(*cmd);
+		fw_size -= sizeof(*cmd);
+
+		if (fw_size < cmd->plen) {
+			BT_ERR("%s: BCM20702: patch %s is corrupted",
+				hdev->name, fw_name);
+			ret = -EINVAL;
+			goto reset_fw;
+		}
+
+		cmd_param = fw_ptr;
+		fw_ptr += cmd->plen;
+		fw_size -= cmd->plen;
+
+		opcode = le16_to_cpu(cmd->opcode);
+
+		skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param,
+				     HCI_INIT_TIMEOUT);
+		if (IS_ERR(skb)) {
+			ret = PTR_ERR(skb);
+			BT_ERR("%s: BCM20702: patch command %04x failed (%ld)",
+				hdev->name, opcode, ret);
+			goto reset_fw;
+		}
+		kfree_skb(skb);
+	}
+
+	/* 250 msec delay after Launch Ram completes */
+	msleep(250);
+
+reset_fw:
+	/* Reset */
+	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret);
+		goto done;
+	}
+	kfree_skb(skb);
+
+get_fw_ver:
+	/* Read Local Version Info */
+	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
+			     HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
+			hdev->name, ret);
+		goto done;
+	}
+
+	ver = (struct hci_rp_read_local_version *) skb->data;
+	BT_INFO("%s: BCM20702: firmware hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
+		"lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev,
+		ver->lmp_ver, ver->lmp_subver);
+	kfree_skb(skb);
+
+done:
+	if (fw)
+		release_firmware(fw);
+
+	return ret;
+}
+
 static int btusb_probe(struct usb_interface *intf,
 				const struct usb_device_id *id)
 {
@@ -1485,6 +1621,9 @@ static int btusb_probe(struct usb_interface *intf,
 	if (id->driver_info & BTUSB_BCM92035)
 		hdev->setup = btusb_setup_bcm92035;
 
+	if (id->driver_info & BTUSB_BCM20702_PATCHRAM)
+		hdev->setup = btusb_setup_bcm20702;
+
 	if (id->driver_info & BTUSB_INTEL) {
 		usb_enable_autosuspend(data->udev);
 		hdev->setup = btusb_setup_intel;
-- 
1.9.1.423.g4596e3a


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

end of thread, other threads:[~2014-05-07 22:28 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-21 10:32 [PATCH] Bluetooth: btusb: Add BCM20702 firmware upgrade support Jesse Sung
2014-04-21 18:19 ` Marcel Holtmann
2014-04-22 12:34   ` Jesse Sung
  -- strict thread matches above, loose matches on Subject: below --
2014-04-09  1:05 Petri Gynther
2014-04-09  1:36 ` Marcel Holtmann
2014-04-09  2:41   ` Petri Gynther
2014-04-09 17:01     ` Marcel Holtmann
2014-04-09 20:06       ` Petri Gynther
2014-04-09 20:57         ` Marcel Holtmann
2014-05-06  2:53           ` Petri Gynther
2014-05-06  6:01             ` Marcel Holtmann
2014-05-07 22:28               ` Petri Gynther

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.