diff options
Diffstat (limited to 'drivers/bluetooth/btusb.c')
| -rw-r--r-- | drivers/bluetooth/btusb.c | 186 | 
1 files changed, 65 insertions, 121 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 92f0ee388f9e..a191e318fab8 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -153,6 +153,10 @@ static const struct usb_device_id btusb_table[] = {  	{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),  	  .driver_info = BTUSB_BCM_PATCHRAM }, +	/* Toshiba Corp - Broadcom based */ +	{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01), +	  .driver_info = BTUSB_BCM_PATCHRAM }, +  	/* Intel Bluetooth USB Bootloader (RAM module) */  	{ USB_DEVICE(0x8087, 0x0a5a),  	  .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC }, @@ -437,22 +441,22 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)  				break;  			} -			bt_cb(skb)->pkt_type = HCI_EVENT_PKT; -			bt_cb(skb)->expect = HCI_EVENT_HDR_SIZE; +			hci_skb_pkt_type(skb) = HCI_EVENT_PKT; +			hci_skb_expect(skb) = HCI_EVENT_HDR_SIZE;  		} -		len = min_t(uint, bt_cb(skb)->expect, count); +		len = min_t(uint, hci_skb_expect(skb), count);  		memcpy(skb_put(skb, len), buffer, len);  		count -= len;  		buffer += len; -		bt_cb(skb)->expect -= len; +		hci_skb_expect(skb) -= len;  		if (skb->len == HCI_EVENT_HDR_SIZE) {  			/* Complete event header */ -			bt_cb(skb)->expect = hci_event_hdr(skb)->plen; +			hci_skb_expect(skb) = hci_event_hdr(skb)->plen; -			if (skb_tailroom(skb) < bt_cb(skb)->expect) { +			if (skb_tailroom(skb) < hci_skb_expect(skb)) {  				kfree_skb(skb);  				skb = NULL; @@ -461,7 +465,7 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)  			}  		} -		if (bt_cb(skb)->expect == 0) { +		if (!hci_skb_expect(skb)) {  			/* Complete frame */  			data->recv_event(data->hdev, skb);  			skb = NULL; @@ -492,24 +496,24 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)  				break;  			} -			bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; -			bt_cb(skb)->expect = HCI_ACL_HDR_SIZE; +			hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT; +			hci_skb_expect(skb) = HCI_ACL_HDR_SIZE;  		} -		len = min_t(uint, bt_cb(skb)->expect, count); +		len = min_t(uint, hci_skb_expect(skb), count);  		memcpy(skb_put(skb, len), buffer, len);  		count -= len;  		buffer += len; -		bt_cb(skb)->expect -= len; +		hci_skb_expect(skb) -= len;  		if (skb->len == HCI_ACL_HDR_SIZE) {  			__le16 dlen = hci_acl_hdr(skb)->dlen;  			/* Complete ACL header */ -			bt_cb(skb)->expect = __le16_to_cpu(dlen); +			hci_skb_expect(skb) = __le16_to_cpu(dlen); -			if (skb_tailroom(skb) < bt_cb(skb)->expect) { +			if (skb_tailroom(skb) < hci_skb_expect(skb)) {  				kfree_skb(skb);  				skb = NULL; @@ -518,7 +522,7 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)  			}  		} -		if (bt_cb(skb)->expect == 0) { +		if (!hci_skb_expect(skb)) {  			/* Complete frame */  			hci_recv_frame(data->hdev, skb);  			skb = NULL; @@ -549,22 +553,22 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)  				break;  			} -			bt_cb(skb)->pkt_type = HCI_SCODATA_PKT; -			bt_cb(skb)->expect = HCI_SCO_HDR_SIZE; +			hci_skb_pkt_type(skb) = HCI_SCODATA_PKT; +			hci_skb_expect(skb) = HCI_SCO_HDR_SIZE;  		} -		len = min_t(uint, bt_cb(skb)->expect, count); +		len = min_t(uint, hci_skb_expect(skb), count);  		memcpy(skb_put(skb, len), buffer, len);  		count -= len;  		buffer += len; -		bt_cb(skb)->expect -= len; +		hci_skb_expect(skb) -= len;  		if (skb->len == HCI_SCO_HDR_SIZE) {  			/* Complete SCO header */ -			bt_cb(skb)->expect = hci_sco_hdr(skb)->dlen; +			hci_skb_expect(skb) = hci_sco_hdr(skb)->dlen; -			if (skb_tailroom(skb) < bt_cb(skb)->expect) { +			if (skb_tailroom(skb) < hci_skb_expect(skb)) {  				kfree_skb(skb);  				skb = NULL; @@ -573,7 +577,7 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)  			}  		} -		if (bt_cb(skb)->expect == 0) { +		if (!hci_skb_expect(skb)) {  			/* Complete frame */  			hci_recv_frame(data->hdev, skb);  			skb = NULL; @@ -1257,7 +1261,7 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  	BT_DBG("%s", hdev->name); -	switch (bt_cb(skb)->pkt_type) { +	switch (hci_skb_pkt_type(skb)) {  	case HCI_COMMAND_PKT:  		urb = alloc_ctrl_urb(hdev, skb);  		if (IS_ERR(urb)) @@ -1642,13 +1646,8 @@ static int btusb_setup_intel(struct hci_dev *hdev)  	struct sk_buff *skb;  	const struct firmware *fw;  	const u8 *fw_ptr; -	int disable_patch; -	struct intel_version *ver; - -	const u8 mfg_enable[] = { 0x01, 0x00 }; -	const u8 mfg_disable[] = { 0x00, 0x00 }; -	const u8 mfg_reset_deactivate[] = { 0x00, 0x01 }; -	const u8 mfg_reset_activate[] = { 0x00, 0x02 }; +	int disable_patch, err; +	struct intel_version ver;  	BT_DBG("%s", hdev->name); @@ -1674,35 +1673,22 @@ static int btusb_setup_intel(struct hci_dev *hdev)  	 * The returned information are hardware variant and revision plus  	 * firmware variant, revision and build number.  	 */ -	skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		BT_ERR("%s reading Intel fw version command failed (%ld)", -		       hdev->name, PTR_ERR(skb)); -		return PTR_ERR(skb); -	} - -	if (skb->len != sizeof(*ver)) { -		BT_ERR("%s Intel version event length mismatch", hdev->name); -		kfree_skb(skb); -		return -EIO; -	} - -	ver = (struct intel_version *)skb->data; +	err = btintel_read_version(hdev, &ver); +	if (err) +		return err;  	BT_INFO("%s: read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x", -		hdev->name, ver->hw_platform, ver->hw_variant, -		ver->hw_revision, ver->fw_variant,  ver->fw_revision, -		ver->fw_build_num, ver->fw_build_ww, ver->fw_build_yy, -		ver->fw_patch_num); +		hdev->name, ver.hw_platform, ver.hw_variant, ver.hw_revision, +		ver.fw_variant,  ver.fw_revision, ver.fw_build_num, +		ver.fw_build_ww, ver.fw_build_yy, ver.fw_patch_num);  	/* fw_patch_num indicates the version of patch the device currently  	 * have. If there is no patch data in the device, it is always 0x00.  	 * So, if it is other than 0x00, no need to patch the device again.  	 */ -	if (ver->fw_patch_num) { +	if (ver.fw_patch_num) {  		BT_INFO("%s: Intel device is already patched. patch num: %02x", -			hdev->name, ver->fw_patch_num); -		kfree_skb(skb); +			hdev->name, ver.fw_patch_num);  		goto complete;  	} @@ -1712,31 +1698,21 @@ static int btusb_setup_intel(struct hci_dev *hdev)  	 * If no patch file is found, allow the device to operate without  	 * a patch.  	 */ -	fw = btusb_setup_intel_get_fw(hdev, ver); -	if (!fw) { -		kfree_skb(skb); +	fw = btusb_setup_intel_get_fw(hdev, &ver); +	if (!fw)  		goto complete; -	}  	fw_ptr = fw->data; -	kfree_skb(skb); - -	/* This Intel specific command enables the manufacturer mode of the -	 * controller. -	 * +	/* Enable the manufacturer mode of the controller.  	 * Only while this mode is enabled, the driver can download the  	 * firmware patch data and configuration parameters.  	 */ -	skb = __hci_cmd_sync(hdev, 0xfc11, 2, mfg_enable, HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		BT_ERR("%s entering Intel manufacturer mode failed (%ld)", -		       hdev->name, PTR_ERR(skb)); +	err = btintel_enter_mfg(hdev); +	if (err) {  		release_firmware(fw); -		return PTR_ERR(skb); +		return err;  	} -	kfree_skb(skb); -  	disable_patch = 1;  	/* The firmware data file consists of list of Intel specific HCI @@ -1776,14 +1752,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)  	/* Patching completed successfully and disable the manufacturer mode  	 * with reset and activate the downloaded firmware patches.  	 */ -	skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_activate), -			     mfg_reset_activate, HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		BT_ERR("%s exiting Intel manufacturer mode failed (%ld)", -		       hdev->name, PTR_ERR(skb)); -		return PTR_ERR(skb); -	} -	kfree_skb(skb); +	err = btintel_exit_mfg(hdev, true, true); +	if (err) +		return err;  	BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",  		hdev->name); @@ -1792,14 +1763,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)  exit_mfg_disable:  	/* Disable the manufacturer mode without reset */ -	skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_disable), mfg_disable, -			     HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		BT_ERR("%s exiting Intel manufacturer mode failed (%ld)", -		       hdev->name, PTR_ERR(skb)); -		return PTR_ERR(skb); -	} -	kfree_skb(skb); +	err = btintel_exit_mfg(hdev, false, false); +	if (err) +		return err;  	BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name); @@ -1811,14 +1777,9 @@ exit_mfg_deactivate:  	/* Patching failed. Disable the manufacturer mode with reset and  	 * deactivate the downloaded firmware patches.  	 */ -	skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_deactivate), -			     mfg_reset_deactivate, HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		BT_ERR("%s exiting Intel manufacturer mode failed (%ld)", -		       hdev->name, PTR_ERR(skb)); -		return PTR_ERR(skb); -	} -	kfree_skb(skb); +	err = btintel_exit_mfg(hdev, true, false); +	if (err) +		return err;  	BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",  		hdev->name); @@ -1853,7 +1814,7 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)  	*skb_put(skb, 1) = 0x00; -	bt_cb(skb)->pkt_type = HCI_EVENT_PKT; +	hci_skb_pkt_type(skb) = HCI_EVENT_PKT;  	return hci_recv_frame(hdev, skb);  } @@ -1945,7 +1906,7 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)  	BT_DBG("%s", hdev->name); -	switch (bt_cb(skb)->pkt_type) { +	switch (hci_skb_pkt_type(skb)) {  	case HCI_COMMAND_PKT:  		if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {  			struct hci_command_hdr *cmd = (void *)skb->data; @@ -2005,7 +1966,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)  					  0x00, 0x08, 0x04, 0x00 };  	struct btusb_data *data = hci_get_drvdata(hdev);  	struct sk_buff *skb; -	struct intel_version *ver; +	struct intel_version ver;  	struct intel_boot_params *params;  	const struct firmware *fw;  	const u8 *fw_ptr; @@ -2023,28 +1984,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)  	 * is in bootloader mode or if it already has operational firmware  	 * loaded.  	 */ -	skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); -	if (IS_ERR(skb)) { -		BT_ERR("%s: Reading Intel version information failed (%ld)", -		       hdev->name, PTR_ERR(skb)); -		return PTR_ERR(skb); -	} - -	if (skb->len != sizeof(*ver)) { -		BT_ERR("%s: Intel version event size mismatch", hdev->name); -		kfree_skb(skb); -		return -EILSEQ; -	} - -	ver = (struct intel_version *)skb->data; +	err = btintel_read_version(hdev, &ver); +	if (err) +		return err;  	/* The hardware platform number has a fixed value of 0x37 and  	 * for now only accept this single value.  	 */ -	if (ver->hw_platform != 0x37) { +	if (ver.hw_platform != 0x37) {  		BT_ERR("%s: Unsupported Intel hardware platform (%u)", -		       hdev->name, ver->hw_platform); -		kfree_skb(skb); +		       hdev->name, ver.hw_platform);  		return -EINVAL;  	} @@ -2053,14 +2002,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)  	 * put in place to ensure correct forward compatibility options  	 * when newer hardware variants come along.  	 */ -	if (ver->hw_variant != 0x0b) { +	if (ver.hw_variant != 0x0b) {  		BT_ERR("%s: Unsupported Intel hardware variant (%u)", -		       hdev->name, ver->hw_variant); -		kfree_skb(skb); +		       hdev->name, ver.hw_variant);  		return -EINVAL;  	} -	btintel_version_info(hdev, ver); +	btintel_version_info(hdev, &ver);  	/* The firmware variant determines if the device is in bootloader  	 * mode or is running operational firmware. The value 0x06 identifies @@ -2075,8 +2023,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)  	 * It is not possible to use the Secure Boot Parameters in this  	 * case since that command is only available in bootloader mode.  	 */ -	if (ver->fw_variant == 0x23) { -		kfree_skb(skb); +	if (ver.fw_variant == 0x23) {  		clear_bit(BTUSB_BOOTLOADER, &data->flags);  		btintel_check_bdaddr(hdev);  		return 0; @@ -2085,15 +2032,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)  	/* If the device is not in bootloader mode, then the only possible  	 * choice is to return an error and abort the device initialization.  	 */ -	if (ver->fw_variant != 0x06) { +	if (ver.fw_variant != 0x06) {  		BT_ERR("%s: Unsupported Intel firmware variant (%u)", -		       hdev->name, ver->fw_variant); -		kfree_skb(skb); +		       hdev->name, ver.fw_variant);  		return -ENODEV;  	} -	kfree_skb(skb); -  	/* Read the secure boot parameters to identify the operating  	 * details of the bootloader.  	 */  | 
