diff options
Diffstat (limited to 'drivers/bluetooth/btusb.c')
| -rw-r--r-- | drivers/bluetooth/btusb.c | 690 | 
1 files changed, 366 insertions, 324 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b87688881143..de7b236eeae7 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -28,7 +28,10 @@  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h> -#define VERSION "0.7" +#include "btintel.h" +#include "btbcm.h" + +#define VERSION "0.8"  static bool disable_scofix;  static bool force_scofix; @@ -52,6 +55,8 @@ static struct usb_driver btusb_driver;  #define BTUSB_SWAVE		0x1000  #define BTUSB_INTEL_NEW		0x2000  #define BTUSB_AMP		0x4000 +#define BTUSB_QCA_ROME		0x8000 +#define BTUSB_BCM_APPLE		0x10000  static const struct usb_device_id btusb_table[] = {  	/* Generic Bluetooth USB device */ @@ -61,7 +66,8 @@ static const struct usb_device_id btusb_table[] = {  	{ USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP },  	/* Apple-specific (Broadcom) devices */ -	{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01), +	  .driver_info = BTUSB_BCM_APPLE },  	/* MediaTek MT76x0E */  	{ USB_DEVICE(0x0e8d, 0x763f) }, @@ -107,13 +113,7 @@ static const struct usb_device_id btusb_table[] = {  	{ USB_DEVICE(0x0c10, 0x0000) },  	/* Broadcom BCM20702A0 */ -	{ USB_DEVICE(0x0489, 0xe042) }, -	{ USB_DEVICE(0x04ca, 0x2003) }, -	{ USB_DEVICE(0x0b05, 0x17b5) }, -	{ USB_DEVICE(0x0b05, 0x17cb) },  	{ USB_DEVICE(0x413c, 0x8197) }, -	{ USB_DEVICE(0x13d3, 0x3404), -	  .driver_info = BTUSB_BCM_PATCHRAM },  	/* Broadcom BCM20702B0 (Dynex/Insignia) */  	{ USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM }, @@ -135,10 +135,12 @@ static const struct usb_device_id btusb_table[] = {  	  .driver_info = BTUSB_BCM_PATCHRAM },  	/* Belkin F8065bf - Broadcom based */ -	{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01), +	  .driver_info = BTUSB_BCM_PATCHRAM },  	/* IMC Networks - Broadcom based */ -	{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01), +	  .driver_info = BTUSB_BCM_PATCHRAM },  	/* Intel Bluetooth USB Bootloader (RAM module) */  	{ USB_DEVICE(0x8087, 0x0a5a), @@ -159,6 +161,7 @@ static const struct usb_device_id blacklist_table[] = {  	/* Atheros 3011 with sflash firmware */  	{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },  	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, +	{ USB_DEVICE(0x04f2, 0xaff1), .driver_info = BTUSB_IGNORE },  	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },  	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },  	{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE }, @@ -212,6 +215,10 @@ static const struct usb_device_id blacklist_table[] = {  	{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, +	/* QCA ROME chipset */ +	{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME }, +	{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME }, +  	/* Broadcom BCM2035 */  	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },  	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, @@ -272,6 +279,7 @@ static const struct usb_device_id blacklist_table[] = {  	{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },  	/* Intel Bluetooth devices */ +	{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },  	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },  	{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },  	{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW }, @@ -336,17 +344,9 @@ struct btusb_data {  	int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb);  	int (*recv_bulk)(struct btusb_data *data, void *buffer, int count); -}; -static int btusb_wait_on_bit_timeout(void *word, int bit, unsigned long timeout, -				     unsigned mode) -{ -	might_sleep(); -	if (!test_bit(bit, word)) -		return 0; -	return out_of_line_wait_on_bit_timeout(word, bit, bit_wait_timeout, -					       mode, timeout); -} +	int (*setup_on_usb)(struct hci_dev *hdev); +};  static inline void btusb_free_frags(struct btusb_data *data)  { @@ -887,6 +887,15 @@ static int btusb_open(struct hci_dev *hdev)  	BT_DBG("%s", hdev->name); +	/* Patching USB firmware files prior to starting any URBs of HCI path +	 * It is more safe to use USB bulk channel for downloading USB patch +	 */ +	if (data->setup_on_usb) { +		err = data->setup_on_usb(hdev); +		if (err <0) +			return err; +	} +  	err = usb_autopm_get_interface(data->intf);  	if (err < 0)  		return err; @@ -1262,6 +1271,28 @@ static void btusb_waker(struct work_struct *work)  	usb_autopm_put_interface(data->intf);  } +static struct sk_buff *btusb_read_local_version(struct hci_dev *hdev) +{ +	struct sk_buff *skb; + +	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, +			     HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)", +		       hdev->name, PTR_ERR(skb)); +		return skb; +	} + +	if (skb->len != sizeof(struct hci_rp_read_local_version)) { +		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", +		       hdev->name); +		kfree_skb(skb); +		return ERR_PTR(-EIO); +	} + +	return skb; +} +  static int btusb_setup_bcm92035(struct hci_dev *hdev)  {  	struct sk_buff *skb; @@ -1286,12 +1317,9 @@ static int btusb_setup_csr(struct hci_dev *hdev)  	BT_DBG("%s", hdev->name); -	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, -			     HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb)); +	skb = btusb_read_local_version(hdev); +	if (IS_ERR(skb))  		return -PTR_ERR(skb); -	}  	rp = (struct hci_rp_read_local_version *)skb->data; @@ -1317,39 +1345,6 @@ static int btusb_setup_csr(struct hci_dev *hdev)  	return ret;  } -struct intel_version { -	u8 status; -	u8 hw_platform; -	u8 hw_variant; -	u8 hw_revision; -	u8 fw_variant; -	u8 fw_revision; -	u8 fw_build_num; -	u8 fw_build_ww; -	u8 fw_build_yy; -	u8 fw_patch_num; -} __packed; - -struct intel_boot_params { -	__u8     status; -	__u8     otp_format; -	__u8     otp_content; -	__u8     otp_patch; -	__le16   dev_revid; -	__u8     secure_boot; -	__u8     key_from_hdr; -	__u8     key_type; -	__u8     otp_lock; -	__u8     api_lock; -	__u8     debug_lock; -	bdaddr_t otp_bdaddr; -	__u8     min_fw_build_nn; -	__u8     min_fw_build_cw; -	__u8     min_fw_build_yy; -	__u8     limited_cce; -	__u8     unlocked_state; -} __packed; -  static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,  						       struct intel_version *ver)  { @@ -1506,51 +1501,6 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,  	return 0;  } -#define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}}) - -static int btusb_check_bdaddr_intel(struct hci_dev *hdev) -{ -	struct sk_buff *skb; -	struct hci_rp_read_bd_addr *rp; - -	skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, -			     HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		BT_ERR("%s reading Intel device address failed (%ld)", -		       hdev->name, PTR_ERR(skb)); -		return PTR_ERR(skb); -	} - -	if (skb->len != sizeof(*rp)) { -		BT_ERR("%s Intel device address length mismatch", hdev->name); -		kfree_skb(skb); -		return -EIO; -	} - -	rp = (struct hci_rp_read_bd_addr *)skb->data; -	if (rp->status) { -		BT_ERR("%s Intel device address result failed (%02x)", -		       hdev->name, rp->status); -		kfree_skb(skb); -		return -bt_to_errno(rp->status); -	} - -	/* For some Intel based controllers, the default Bluetooth device -	 * address 00:03:19:9E:8B:00 can be found. These controllers are -	 * fully operational, but have the danger of duplicate addresses -	 * and that in turn can cause problems with Bluetooth operation. -	 */ -	if (!bacmp(&rp->bdaddr, BDADDR_INTEL)) { -		BT_ERR("%s found Intel default device address (%pMR)", -		       hdev->name, &rp->bdaddr); -		set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); -	} - -	kfree_skb(skb); - -	return 0; -} -  static int btusb_setup_intel(struct hci_dev *hdev)  {  	struct sk_buff *skb; @@ -1623,7 +1573,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)  		BT_INFO("%s: Intel device is already patched. patch num: %02x",  			hdev->name, ver->fw_patch_num);  		kfree_skb(skb); -		btusb_check_bdaddr_intel(hdev); +		btintel_check_bdaddr(hdev);  		return 0;  	} @@ -1636,7 +1586,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)  	fw = btusb_setup_intel_get_fw(hdev, ver);  	if (!fw) {  		kfree_skb(skb); -		btusb_check_bdaddr_intel(hdev); +		btintel_check_bdaddr(hdev);  		return 0;  	}  	fw_ptr = fw->data; @@ -1717,7 +1667,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)  	BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",  		hdev->name); -	btusb_check_bdaddr_intel(hdev); +	btintel_check_bdaddr(hdev);  	return 0;  exit_mfg_disable: @@ -1733,7 +1683,7 @@ exit_mfg_disable:  	BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name); -	btusb_check_bdaddr_intel(hdev); +	btintel_check_bdaddr(hdev);  	return 0;  exit_mfg_deactivate: @@ -1754,7 +1704,7 @@ exit_mfg_deactivate:  	BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",  		hdev->name); -	btusb_check_bdaddr_intel(hdev); +	btintel_check_bdaddr(hdev);  	return 0;  } @@ -1796,6 +1746,38 @@ static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer,  	return btusb_recv_bulk(data, buffer, count);  } +static void btusb_intel_bootup(struct btusb_data *data, const void *ptr, +			       unsigned int len) +{ +	const struct intel_bootup *evt = ptr; + +	if (len != sizeof(*evt)) +		return; + +	if (test_and_clear_bit(BTUSB_BOOTING, &data->flags)) { +		smp_mb__after_atomic(); +		wake_up_bit(&data->flags, BTUSB_BOOTING); +	} +} + +static void btusb_intel_secure_send_result(struct btusb_data *data, +					   const void *ptr, unsigned int len) +{ +	const struct intel_secure_send_result *evt = ptr; + +	if (len != sizeof(*evt)) +		return; + +	if (evt->result) +		set_bit(BTUSB_FIRMWARE_FAILED, &data->flags); + +	if (test_and_clear_bit(BTUSB_DOWNLOADING, &data->flags) && +	    test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) { +		smp_mb__after_atomic(); +		wake_up_bit(&data->flags, BTUSB_DOWNLOADING); +	} +} +  static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb)  {  	struct btusb_data *data = hci_get_drvdata(hdev); @@ -1803,32 +1785,27 @@ static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb)  	if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {  		struct hci_event_hdr *hdr = (void *)skb->data; -		/* When the firmware loading completes the device sends -		 * out a vendor specific event indicating the result of -		 * the firmware loading. -		 */ -		if (skb->len == 7 && hdr->evt == 0xff && hdr->plen == 0x05 && -		    skb->data[2] == 0x06) { -			if (skb->data[3] != 0x00) -				test_bit(BTUSB_FIRMWARE_FAILED, &data->flags); - -			if (test_and_clear_bit(BTUSB_DOWNLOADING, -					       &data->flags) && -			    test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) { -				smp_mb__after_atomic(); -				wake_up_bit(&data->flags, BTUSB_DOWNLOADING); -			} -		} - -		/* When switching to the operational firmware the device -		 * sends a vendor specific event indicating that the bootup -		 * completed. -		 */ -		if (skb->len == 9 && hdr->evt == 0xff && hdr->plen == 0x07 && -		    skb->data[2] == 0x02) { -			if (test_and_clear_bit(BTUSB_BOOTING, &data->flags)) { -				smp_mb__after_atomic(); -				wake_up_bit(&data->flags, BTUSB_BOOTING); +		if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff && +		    hdr->plen > 0) { +			const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1; +			unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1; + +			switch (skb->data[2]) { +			case 0x02: +				/* When switching to the operational firmware +				 * the device sends a vendor specific event +				 * indicating that the bootup completed. +				 */ +				btusb_intel_bootup(data, ptr, len); +				break; +			case 0x06: +				/* When the firmware loading completes the +				 * device sends out a vendor specific event +				 * indicating the result of the firmware +				 * loading. +				 */ +				btusb_intel_secure_send_result(data, ptr, len); +				break;  			}  		}  	} @@ -2030,7 +2007,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)  	if (ver->fw_variant == 0x23) {  		kfree_skb(skb);  		clear_bit(BTUSB_BOOTLOADER, &data->flags); -		btusb_check_bdaddr_intel(hdev); +		btintel_check_bdaddr(hdev);  		return 0;  	} @@ -2196,9 +2173,9 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)  	 * and thus just timeout if that happens and fail the setup  	 * of this device.  	 */ -	err = btusb_wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING, -					msecs_to_jiffies(5000), -					TASK_INTERRUPTIBLE); +	err = wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING, +				  TASK_INTERRUPTIBLE, +				  msecs_to_jiffies(5000));  	if (err == 1) {  		BT_ERR("%s: Firmware loading interrupted", hdev->name);  		err = -EINTR; @@ -2249,9 +2226,9 @@ done:  	 */  	BT_INFO("%s: Waiting for device to boot", hdev->name); -	err = btusb_wait_on_bit_timeout(&data->flags, BTUSB_BOOTING, -					msecs_to_jiffies(1000), -					TASK_INTERRUPTIBLE); +	err = wait_on_bit_timeout(&data->flags, BTUSB_BOOTING, +				  TASK_INTERRUPTIBLE, +				  msecs_to_jiffies(1000));  	if (err == 1) {  		BT_ERR("%s: Device boot interrupted", hdev->name); @@ -2314,15 +2291,19 @@ static void btusb_hw_error_intel(struct hci_dev *hdev, u8 code)  	kfree_skb(skb);  } -static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr) +static int btusb_shutdown_intel(struct hci_dev *hdev)  {  	struct sk_buff *skb;  	long ret; -	skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT); +	/* Some platforms have an issue with BT LED when the interface is +	 * down or BT radio is turned off, which takes 5 seconds to BT LED +	 * goes off. This command turns off the BT LED immediately. +	 */ +	skb = __hci_cmd_sync(hdev, 0xfc3f, 0, NULL, HCI_INIT_TIMEOUT);  	if (IS_ERR(skb)) {  		ret = PTR_ERR(skb); -		BT_ERR("%s: changing Intel device address failed (%ld)", +		BT_ERR("%s: turning off Intel device LED failed (%ld)",  		       hdev->name, ret);  		return ret;  	} @@ -2354,232 +2335,279 @@ static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,  	return 0;  } -#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) - -static int btusb_setup_bcm_patchram(struct hci_dev *hdev) +static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev, +				    const bdaddr_t *bdaddr)  { -	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; -	struct hci_rp_read_bd_addr *bda; +	u8 buf[10];  	long ret; -	snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd", -		 udev->product ? udev->product : "BCM", -		 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: BCM: patch %s not found", hdev->name, fw_name); -		return 0; -	} +	buf[0] = 0x01; +	buf[1] = 0x01; +	buf[2] = 0x00; +	buf[3] = sizeof(bdaddr_t); +	memcpy(buf + 4, bdaddr, sizeof(bdaddr_t)); -	/* Reset */ -	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); +	skb = __hci_cmd_sync(hdev, 0xfc0b, sizeof(buf), buf, HCI_INIT_TIMEOUT);  	if (IS_ERR(skb)) {  		ret = PTR_ERR(skb); -		BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret); -		goto done; +		BT_ERR("%s: Change address command failed (%ld)", +		       hdev->name, ret); +		return ret;  	}  	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 done; -	} +	return 0; +} -	if (skb->len != sizeof(*ver)) { -		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", -		       hdev->name); -		kfree_skb(skb); -		ret = -EIO; -		goto done; -	} +#define QCA_DFU_PACKET_LEN	4096 -	ver = (struct hci_rp_read_local_version *)skb->data; -	BT_INFO("%s: BCM: 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); +#define QCA_GET_TARGET_VERSION	0x09 +#define QCA_CHECK_STATUS	0x05 +#define QCA_DFU_DOWNLOAD	0x01 -	/* Start Download */ -	skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		ret = PTR_ERR(skb); -		BT_ERR("%s: BCM: Download Minidrv command failed (%ld)", -		       hdev->name, ret); -		goto reset_fw; -	} -	kfree_skb(skb); +#define QCA_SYSCFG_UPDATED	0x40 +#define QCA_PATCH_UPDATED	0x80 +#define QCA_DFU_TIMEOUT		3000 -	/* 50 msec delay after Download Minidrv completes */ -	msleep(50); +struct qca_version { +	__le32	rom_version; +	__le32	patch_version; +	__le32	ram_version; +	__le32	ref_clock; +	__u8	reserved[4]; +} __packed; -	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: BCM: patch %s is corrupted", -			       hdev->name, fw_name); -			ret = -EINVAL; -			goto reset_fw; -		} +struct qca_rampatch_version { +	__le16	rom_version; +	__le16	patch_version; +} __packed; -		cmd_param = fw_ptr; -		fw_ptr += cmd->plen; -		fw_size -= cmd->plen; +struct qca_device_info { +	u32	rom_version; +	u8	rampatch_hdr;	/* length of header in rampatch */ +	u8	nvm_hdr;	/* length of header in NVM */ +	u8	ver_offset;	/* offset of version structure in rampatch */ +}; -		opcode = le16_to_cpu(cmd->opcode); +static const struct qca_device_info qca_devices_table[] = { +	{ 0x00000100, 20, 4, 10 }, /* Rome 1.0 */ +	{ 0x00000101, 20, 4, 10 }, /* Rome 1.1 */ +	{ 0x00000201, 28, 4, 18 }, /* Rome 2.1 */ +	{ 0x00000300, 28, 4, 18 }, /* Rome 3.0 */ +	{ 0x00000302, 28, 4, 18 }, /* Rome 3.2 */ +}; -		skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param, -				     HCI_INIT_TIMEOUT); -		if (IS_ERR(skb)) { -			ret = PTR_ERR(skb); -			BT_ERR("%s: BCM: patch command %04x failed (%ld)", -			       hdev->name, opcode, ret); -			goto reset_fw; -		} -		kfree_skb(skb); -	} +static int btusb_qca_send_vendor_req(struct hci_dev *hdev, u8 request, +				     void *data, u16 size) +{ +	struct btusb_data *btdata = hci_get_drvdata(hdev); +	struct usb_device *udev = btdata->udev; +	int pipe, err; +	u8 *buf; -	/* 250 msec delay after Launch Ram completes */ -	msleep(250); +	buf = kmalloc(size, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; -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); +	/* Found some of USB hosts have IOT issues with ours so that we should +	 * not wait until HCI layer is ready. +	 */ +	pipe = usb_rcvctrlpipe(udev, 0); +	err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN, +			      0, 0, buf, size, USB_CTRL_SET_TIMEOUT); +	if (err < 0) { +		BT_ERR("%s: Failed to access otp area (%d)", hdev->name, err);  		goto done;  	} -	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 done; -	} +	memcpy(data, buf, size); -	if (skb->len != sizeof(*ver)) { -		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", -		       hdev->name); -		kfree_skb(skb); -		ret = -EIO; -		goto done; -	} +done: +	kfree(buf); -	ver = (struct hci_rp_read_local_version *)skb->data; -	BT_INFO("%s: BCM: 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); +	return err; +} -	/* Read BD Address */ -	skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, -			     HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		ret = PTR_ERR(skb); -		BT_ERR("%s: HCI_OP_READ_BD_ADDR failed (%ld)", -		       hdev->name, ret); +static int btusb_setup_qca_download_fw(struct hci_dev *hdev, +				       const struct firmware *firmware, +				       size_t hdr_size) +{ +	struct btusb_data *btdata = hci_get_drvdata(hdev); +	struct usb_device *udev = btdata->udev; +	size_t count, size, sent = 0; +	int pipe, len, err; +	u8 *buf; + +	buf = kmalloc(QCA_DFU_PACKET_LEN, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	count = firmware->size; + +	size = min_t(size_t, count, hdr_size); +	memcpy(buf, firmware->data, size); + +	/* USB patches should go down to controller through USB path +	 * because binary format fits to go down through USB channel. +	 * USB control path is for patching headers and USB bulk is for +	 * patch body. +	 */ +	pipe = usb_sndctrlpipe(udev, 0); +	err = usb_control_msg(udev, pipe, QCA_DFU_DOWNLOAD, USB_TYPE_VENDOR, +			      0, 0, buf, size, USB_CTRL_SET_TIMEOUT); +	if (err < 0) { +		BT_ERR("%s: Failed to send headers (%d)", hdev->name, err);  		goto done;  	} -	if (skb->len != sizeof(*bda)) { -		BT_ERR("%s: HCI_OP_READ_BD_ADDR event length mismatch", -		       hdev->name); -		kfree_skb(skb); -		ret = -EIO; -		goto done; +	sent += size; +	count -= size; + +	while (count) { +		size = min_t(size_t, count, QCA_DFU_PACKET_LEN); + +		memcpy(buf, firmware->data + sent, size); + +		pipe = usb_sndbulkpipe(udev, 0x02); +		err = usb_bulk_msg(udev, pipe, buf, size, &len, +				   QCA_DFU_TIMEOUT); +		if (err < 0) { +			BT_ERR("%s: Failed to send body at %zd of %zd (%d)", +			       hdev->name, sent, firmware->size, err); +			break; +		} + +		if (size != len) { +			BT_ERR("%s: Failed to get bulk buffer", hdev->name); +			err = -EILSEQ; +			break; +		} + +		sent  += size; +		count -= size;  	} -	bda = (struct hci_rp_read_bd_addr *)skb->data; -	if (bda->status) { -		BT_ERR("%s: HCI_OP_READ_BD_ADDR error status (%02x)", -		       hdev->name, bda->status); -		kfree_skb(skb); -		ret = -bt_to_errno(bda->status); -		goto done; +done: +	kfree(buf); +	return err; +} + +static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev, +					 struct qca_version *ver, +					 const struct qca_device_info *info) +{ +	struct qca_rampatch_version *rver; +	const struct firmware *fw; +	u32 ver_rom, ver_patch; +	u16 rver_rom, rver_patch; +	char fwname[64]; +	int err; + +	ver_rom = le32_to_cpu(ver->rom_version); +	ver_patch = le32_to_cpu(ver->patch_version); + +	snprintf(fwname, sizeof(fwname), "qca/rampatch_usb_%08x.bin", ver_rom); + +	err = request_firmware(&fw, fwname, &hdev->dev); +	if (err) { +		BT_ERR("%s: failed to request rampatch file: %s (%d)", +		       hdev->name, fwname, err); +		return err;  	} -	/* The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller -	 * with no configured address. -	 */ -	if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0)) { -		BT_INFO("%s: BCM: using default device address (%pMR)", -			hdev->name, &bda->bdaddr); -		set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); +	BT_INFO("%s: using rampatch file: %s", hdev->name, fwname); + +	rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset); +	rver_rom = le16_to_cpu(rver->rom_version); +	rver_patch = le16_to_cpu(rver->patch_version); + +	BT_INFO("%s: QCA: patch rome 0x%x build 0x%x, firmware rome 0x%x " +		"build 0x%x", hdev->name, rver_rom, rver_patch, ver_rom, +		ver_patch); + +	if (rver_rom != ver_rom || rver_patch <= ver_patch) { +		BT_ERR("%s: rampatch file version did not match with firmware", +		       hdev->name); +		err = -EINVAL; +		goto done;  	} -	kfree_skb(skb); +	err = btusb_setup_qca_download_fw(hdev, fw, info->rampatch_hdr);  done:  	release_firmware(fw); -	return ret; +	return err;  } -static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr) +static int btusb_setup_qca_load_nvm(struct hci_dev *hdev, +				    struct qca_version *ver, +				    const struct qca_device_info *info)  { -	struct sk_buff *skb; -	long ret; +	const struct firmware *fw; +	char fwname[64]; +	int err; -	skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		ret = PTR_ERR(skb); -		BT_ERR("%s: BCM: Change address command failed (%ld)", -		       hdev->name, ret); -		return ret; +	snprintf(fwname, sizeof(fwname), "qca/nvm_usb_%08x.bin", +		 le32_to_cpu(ver->rom_version)); + +	err = request_firmware(&fw, fwname, &hdev->dev); +	if (err) { +		BT_ERR("%s: failed to request NVM file: %s (%d)", +		       hdev->name, fwname, err); +		return err;  	} -	kfree_skb(skb); -	return 0; +	BT_INFO("%s: using NVM file: %s", hdev->name, fwname); + +	err = btusb_setup_qca_download_fw(hdev, fw, info->nvm_hdr); + +	release_firmware(fw); + +	return err;  } -static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev, -				    const bdaddr_t *bdaddr) +static int btusb_setup_qca(struct hci_dev *hdev)  { -	struct sk_buff *skb; -	u8 buf[10]; -	long ret; +	const struct qca_device_info *info = NULL; +	struct qca_version ver; +	u32 ver_rom; +	u8 status; +	int i, err; -	buf[0] = 0x01; -	buf[1] = 0x01; -	buf[2] = 0x00; -	buf[3] = sizeof(bdaddr_t); -	memcpy(buf + 4, bdaddr, sizeof(bdaddr_t)); +	err = btusb_qca_send_vendor_req(hdev, QCA_GET_TARGET_VERSION, &ver, +				        sizeof(ver)); +	if (err < 0) +		return err; -	skb = __hci_cmd_sync(hdev, 0xfc0b, sizeof(buf), buf, HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		ret = PTR_ERR(skb); -		BT_ERR("%s: Change address command failed (%ld)", -		       hdev->name, ret); -		return ret; +	ver_rom = le32_to_cpu(ver.rom_version); +	for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) { +		if (ver_rom == qca_devices_table[i].rom_version) +			info = &qca_devices_table[i]; +	} +	if (!info) { +		BT_ERR("%s: don't support firmware rome 0x%x", hdev->name, +		       ver_rom); +		return -ENODEV; +	} + +	err = btusb_qca_send_vendor_req(hdev, QCA_CHECK_STATUS, &status, +					sizeof(status)); +	if (err < 0) +		return err; + +	if (!(status & QCA_PATCH_UPDATED)) { +		err = btusb_setup_qca_load_rampatch(hdev, &ver, info); +		if (err < 0) +			return err; +	} + +	if (!(status & QCA_SYSCFG_UPDATED)) { +		err = btusb_setup_qca_load_nvm(hdev, &ver, info); +		if (err < 0) +			return err;  	} -	kfree_skb(skb);  	return 0;  } @@ -2700,23 +2728,29 @@ static int btusb_probe(struct usb_interface *intf,  	if (id->driver_info & BTUSB_BCM92035)  		hdev->setup = btusb_setup_bcm92035; +#ifdef CONFIG_BT_HCIBTUSB_BCM  	if (id->driver_info & BTUSB_BCM_PATCHRAM) { -		hdev->setup = btusb_setup_bcm_patchram; -		hdev->set_bdaddr = btusb_set_bdaddr_bcm; -		set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); +		hdev->setup = btbcm_setup_patchram; +		hdev->set_bdaddr = btbcm_set_bdaddr;  	} +	if (id->driver_info & BTUSB_BCM_APPLE) +		hdev->setup = btbcm_setup_apple; +#endif +  	if (id->driver_info & BTUSB_INTEL) {  		hdev->setup = btusb_setup_intel; -		hdev->set_bdaddr = btusb_set_bdaddr_intel; +		hdev->shutdown = btusb_shutdown_intel; +		hdev->set_bdaddr = btintel_set_bdaddr;  		set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); +		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);  	}  	if (id->driver_info & BTUSB_INTEL_NEW) {  		hdev->send = btusb_send_frame_intel;  		hdev->setup = btusb_setup_intel_new;  		hdev->hw_error = btusb_hw_error_intel; -		hdev->set_bdaddr = btusb_set_bdaddr_intel; +		hdev->set_bdaddr = btintel_set_bdaddr;  		set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);  	} @@ -2733,9 +2767,15 @@ static int btusb_probe(struct usb_interface *intf,  	if (id->driver_info & BTUSB_ATH3012) {  		hdev->set_bdaddr = btusb_set_bdaddr_ath3012; +		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);  		set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);  	} +	if (id->driver_info & BTUSB_QCA_ROME) { +		data->setup_on_usb = btusb_setup_qca; +		hdev->set_bdaddr = btusb_set_bdaddr_ath3012; +	} +  	if (id->driver_info & BTUSB_AMP) {  		/* AMP controllers do not support SCO packets */  		data->isoc = NULL; @@ -2771,6 +2811,8 @@ static int btusb_probe(struct usb_interface *intf,  		/* Fake CSR devices with broken commands */  		if (bcdDevice <= 0x100)  			hdev->setup = btusb_setup_csr; + +		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);  	}  	if (id->driver_info & BTUSB_SNIFFER) {  |