2015-04-16 20:09:55

by Daniel Drake

[permalink] [raw]
Subject: [PATCH v8] Bluetooth: btusb: Add Realtek 8723A/8723B/8761A/8821A support

Realtek ship a variety of bluetooth USB devices that identify
themselves with standard USB Bluetooth device class values, but
require a special driver to actually work. Without that driver,
you never get any scan results.

More recently however, Realtek appear to have wisened up and simply
posted a firmware update that makes these devices comply with
normal btusb protocols. The firmware needs to be uploaded on each boot.

Based on Realtek code from https://github.com/lwfinger/rtl8723au_bt
('new' branch).

This enables bluetooth support in the Gigabyte Brix GB-BXBT-2807 which
has this RTL8723BE USB device:

T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=12 MxCh= 0
D: Ver= 2.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=13d3 ProdID=3410 Rev= 2.00
S: Manufacturer=Realtek
S: Product=Bluetooth Radio
S: SerialNumber=00e04c000001
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms

There is no change to the USB descriptor after firmware update,
however the version read by HCI_OP_READ_LOCAL_VERSION changes from
0x8723 to 0x3083.

This has also been tested on RTL8723AE and RTL8821AE. Support for
RTL8761A has also been added, but that is untested.

Signed-off-by: Daniel Drake <[email protected]>
Tested-by: Larry Finger <[email protected]>
---
drivers/bluetooth/btusb.c | 399 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 399 insertions(+)

v8:
- minor cleanups
- remove suspend/resume support, this will be submitted later, separately

v7:
- Rebase on bluetooth-next
- Add suspend/resume support

v6:
- Really add firmware log message.

v5:
- log firmware filename before loading it
- this has passed testing from Larry and friends

v4:
- Simplify ID matching: match just the Realtek vendor, and the non-Realtek
device IDs. Specific chip detection is then done with READ_LOCAL_VERSION.
- Endianness fixes
- Addressed other review comments

v3:
- Removed support for devices where we don't have firmware
- Divide 8723A/8723B codepaths based on driver_info constant
- Added more device IDs from latest Realtek code
- Addressed minor review comments
- Rename RTK --> RTL

v2:
- share main blacklist table with other devices
- epatch table parsing endian/alignment fixes
- BT_INFO message to inform user
- added missing kmalloc error check
- fixed skb leak
- style fixes

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index de7b236..84f9985 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 <asm/unaligned.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -57,6 +58,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_AMP 0x4000
#define BTUSB_QCA_ROME 0x8000
#define BTUSB_BCM_APPLE 0x10000
+#define BTUSB_REALTEK 0x20000

static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -288,6 +290,28 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
.driver_info = BTUSB_IGNORE },

+ /* Realtek Bluetooth devices */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
+ .driver_info = BTUSB_REALTEK },
+
+ /* Additional Realtek 8723AE Bluetooth devices */
+ { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK },
+
+ /* Additional Realtek 8723BE Bluetooth devices */
+ { USB_DEVICE(0x0489, 0xe085), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x0489, 0xe08b), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
+
+ /* Additional Realtek 8821AE Bluetooth devices */
+ { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3458), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
+
{ } /* Terminating entry */
};

@@ -1345,6 +1369,378 @@ static int btusb_setup_csr(struct hci_dev *hdev)
return ret;
}

+#define RTL_FRAG_LEN 252
+
+struct rtl_download_cmd {
+ __u8 index;
+ __u8 data[RTL_FRAG_LEN];
+} __packed;
+
+struct rtl_download_response {
+ __u8 status;
+ __u8 index;
+} __packed;
+
+struct rtl_rom_version_evt {
+ __u8 status;
+ __u8 version;
+} __packed;
+
+struct rtl_epatch_header {
+ __u8 signature[8];
+ __le32 fw_version;
+ __le16 num_patches;
+} __packed;
+
+#define RTL_EPATCH_SIGNATURE "Realtech"
+#define RTL_ROM_LMP_3499 0x3499
+#define RTL_ROM_LMP_8723A 0x1200
+#define RTL_ROM_LMP_8723B 0x8723
+#define RTL_ROM_LMP_8821A 0x8821
+#define RTL_ROM_LMP_8761A 0x8761
+
+static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version)
+{
+ struct rtl_rom_version_evt *rom_version;
+ struct sk_buff *skb;
+ int ret;
+
+ /* Read RTL ROM version command */
+ skb = __hci_cmd_sync(hdev, 0xfc6d, 0, NULL, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ BT_ERR("%s: Read ROM version failed (%ld)",
+ hdev->name, PTR_ERR(skb));
+ return PTR_ERR(skb);
+ }
+
+ if (skb->len != sizeof(*rom_version)) {
+ BT_ERR("%s: RTL version event length mismatch", hdev->name);
+ kfree_skb(skb);
+ return -EIO;
+ }
+
+ rom_version = (struct rtl_rom_version_evt *)skb->data;
+ BT_INFO("%s: rom_version status=%x version=%x",
+ hdev->name, rom_version->status, rom_version->version);
+
+ ret = rom_version->status;
+ if (ret == 0)
+ *version = rom_version->version;
+
+ kfree_skb(skb);
+ return ret;
+}
+
+static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver,
+ const struct firmware *fw,
+ unsigned char **_buf)
+{
+ const u8 extension_sig[] = { 0x51, 0x04, 0xfd, 0x77 };
+ struct rtl_epatch_header *epatch_info;
+ unsigned char *buf;
+ int i, ret, len;
+ size_t min_size;
+ u8 opcode, length, data, rom_version = 0;
+ int project_id = -1;
+ const unsigned char *fwptr, *chip_id_base;
+ const unsigned char *patch_length_base, *patch_offset_base;
+ u32 patch_offset = 0;
+ u16 patch_length, num_patches;
+ const u16 project_id_to_lmp_subver[] = {
+ RTL_ROM_LMP_8723A,
+ RTL_ROM_LMP_8723B,
+ RTL_ROM_LMP_8821A,
+ RTL_ROM_LMP_8761A
+ };
+
+ ret = rtl_read_rom_version(hdev, &rom_version);
+ if (ret)
+ return -bt_to_errno(ret);
+
+ min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3;
+ if (fw->size < min_size)
+ return -EINVAL;
+
+ fwptr = fw->data + fw->size - sizeof(extension_sig);
+ if (memcmp(fwptr, extension_sig, sizeof(extension_sig)) != 0) {
+ BT_ERR("%s: extension section signature mismatch", hdev->name);
+ return -EINVAL;
+ }
+
+ /* Loop from the end of the firmware parsing instructions, until
+ * we find an instruction that identifies the "project ID" for the
+ * hardware supported by this firwmare file.
+ * Once we have that, we double-check that that project_id is suitable
+ * for the hardware we are working with.
+ */
+ while (fwptr >= fw->data + (sizeof(struct rtl_epatch_header) + 3)) {
+ opcode = *--fwptr;
+ length = *--fwptr;
+ data = *--fwptr;
+
+ BT_DBG("check op=%x len=%x data=%x", opcode, length, data);
+
+ if (opcode == 0xff) /* EOF */
+ break;
+
+ if (length == 0) {
+ BT_ERR("%s: found instruction with length 0",
+ hdev->name);
+ return -EINVAL;
+ }
+
+ if (opcode == 0 && length == 1) {
+ project_id = data;
+ break;
+ }
+
+ fwptr -= length;
+ }
+
+ if (project_id < 0) {
+ BT_ERR("%s: failed to find version instruction", hdev->name);
+ return -EINVAL;
+ }
+
+ if (project_id > ARRAY_SIZE(project_id_to_lmp_subver)) {
+ BT_ERR("%s: unknown project id %d", hdev->name, project_id);
+ return -EINVAL;
+ }
+
+ if (lmp_subver != project_id_to_lmp_subver[project_id]) {
+ BT_ERR("%s: firmware is for %x but this is a %x", hdev->name,
+ project_id_to_lmp_subver[project_id], lmp_subver);
+ return -EINVAL;
+ }
+
+ epatch_info = (struct rtl_epatch_header *)fw->data;
+ if (memcmp(epatch_info->signature, RTL_EPATCH_SIGNATURE, 8) != 0) {
+ BT_ERR("%s: bad EPATCH signature", hdev->name);
+ return -EINVAL;
+ }
+
+ num_patches = le16_to_cpu(epatch_info->num_patches);
+ BT_DBG("fw_version=%x, num_patches=%d",
+ le32_to_cpu(epatch_info->fw_version), num_patches);
+
+ /* After the rtl_epatch_header there is a funky patch metadata section.
+ * Assuming 2 patches, the layout is:
+ * ChipID1 ChipID2 PatchLength1 PatchLength2 PatchOffset1 PatchOffset2
+ *
+ * Find the right patch for this chip.
+ */
+ min_size += 8 * num_patches;
+ if (fw->size < min_size)
+ return -EINVAL;
+
+ chip_id_base = fw->data + sizeof(struct rtl_epatch_header);
+ patch_length_base = chip_id_base + (sizeof(u16) * num_patches);
+ patch_offset_base = patch_length_base + (sizeof(u16) * num_patches);
+ for (i = 0; i < num_patches; i++) {
+ u16 chip_id = get_unaligned_le16(chip_id_base +
+ (i * sizeof(u16)));
+ if (chip_id == rom_version + 1) {
+ patch_length = get_unaligned_le16(patch_length_base +
+ (i * sizeof(u16)));
+ patch_offset = get_unaligned_le32(patch_offset_base +
+ (i * sizeof(u32)));
+ break;
+ }
+ }
+
+ if (!patch_offset) {
+ BT_ERR("%s: didn't find patch for chip id %d",
+ hdev->name, rom_version);
+ return -EINVAL;
+ }
+
+ BT_DBG("length=%x offset=%x index %d", patch_length, patch_offset, i);
+ min_size = patch_offset + patch_length;
+ if (fw->size < min_size)
+ return -EINVAL;
+
+ /* Copy the firmware into a new buffer and write the version at
+ * the end.
+ */
+ len = patch_length;
+ buf = kmemdup(fw->data + patch_offset, patch_length, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy(buf + patch_length - 4, &epatch_info->fw_version, 4);
+
+ *_buf = buf;
+ return len;
+}
+
+static int rtl_download_firmware(struct hci_dev *hdev,
+ const unsigned char *data, int fw_len)
+{
+ struct rtl_download_cmd *dl_cmd;
+ int frag_num = fw_len / RTL_FRAG_LEN + 1;
+ int frag_len = RTL_FRAG_LEN;
+ int ret = 0;
+ int i;
+
+ dl_cmd = kmalloc(sizeof(struct rtl_download_cmd), GFP_KERNEL);
+ if (!dl_cmd)
+ return -ENOMEM;
+
+ for (i = 0; i < frag_num; i++) {
+ struct rtl_download_response *dl_resp;
+ struct sk_buff *skb;
+
+ BT_DBG("download fw (%d/%d)", i, frag_num);
+
+ dl_cmd->index = i;
+ if (i == (frag_num - 1)) {
+ dl_cmd->index |= 0x80; /* data end */
+ frag_len = fw_len % RTL_FRAG_LEN;
+ }
+ memcpy(dl_cmd->data, data, frag_len);
+
+ /* Send download command */
+ skb = __hci_cmd_sync(hdev, 0xfc20, frag_len + 1, dl_cmd,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ BT_ERR("%s: download fw command failed (%ld)",
+ hdev->name, PTR_ERR(skb));
+ ret = -PTR_ERR(skb);
+ goto out;
+ }
+
+ if (skb->len != sizeof(*dl_resp)) {
+ BT_ERR("%s: download fw event length mismatch",
+ hdev->name);
+ kfree_skb(skb);
+ ret = -EIO;
+ goto out;
+ }
+
+ dl_resp = (struct rtl_download_response *)skb->data;
+ if (dl_resp->status != 0) {
+ kfree_skb(skb);
+ ret = bt_to_errno(dl_resp->status);
+ goto out;
+ }
+
+ kfree_skb(skb);
+ data += RTL_FRAG_LEN;
+ }
+
+out:
+ kfree(dl_cmd);
+ return ret;
+}
+
+static int btusb_setup_rtl8723a(struct hci_dev *hdev)
+{
+ struct btusb_data *data = dev_get_drvdata(&hdev->dev);
+ struct usb_device *udev = interface_to_usbdev(data->intf);
+ const struct firmware *fw;
+ int ret;
+
+ BT_INFO("%s: rtl: loading rtl_bt/rtl8723a_fw.bin", hdev->name);
+ ret = request_firmware(&fw, "rtl_bt/rtl8723a_fw.bin", &udev->dev);
+ if (ret < 0) {
+ BT_ERR("%s: Failed to load rtl_bt/rtl8723a_fw.bin", hdev->name);
+ return ret;
+ }
+
+ if (fw->size < 8) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Check that the firmware doesn't have the epatch signature
+ * (which is only for RTL8723B and newer).
+ */
+ if (!memcmp(fw->data, RTL_EPATCH_SIGNATURE, 8)) {
+ BT_ERR("%s: unexpected EPATCH signature!", hdev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = rtl_download_firmware(hdev, fw->data, fw->size);
+
+out:
+ release_firmware(fw);
+ return ret;
+}
+
+static int btusb_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
+ const char *fw_name)
+{
+ struct btusb_data *data = dev_get_drvdata(&hdev->dev);
+ struct usb_device *udev = interface_to_usbdev(data->intf);
+ unsigned char *fw_data = NULL;
+ const struct firmware *fw;
+ int ret;
+
+ BT_INFO("%s: rtl: loading %s", hdev->name, fw_name);
+ ret = request_firmware(&fw, fw_name, &udev->dev);
+ if (ret < 0) {
+ BT_ERR("%s: Failed to load %s", hdev->name, fw_name);
+ return ret;
+ }
+
+ ret = rtl8723b_parse_firmware(hdev, lmp_subver, fw, &fw_data);
+ if (ret < 0)
+ goto out;
+
+ ret = rtl_download_firmware(hdev, fw_data, ret);
+ kfree(fw_data);
+ if (ret < 0)
+ goto out;
+
+out:
+ release_firmware(fw);
+ return ret;
+}
+
+static int btusb_setup_realtek(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+ struct hci_rp_read_local_version *resp;
+ u16 lmp_subver;
+
+ skb = btusb_read_local_version(hdev);
+ if (IS_ERR(skb))
+ return -PTR_ERR(skb);
+
+ resp = (struct hci_rp_read_local_version *)skb->data;
+ BT_INFO("%s: rtl: examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
+ "lmp_subver=%04x", hdev->name, resp->hci_ver, resp->hci_rev,
+ resp->lmp_ver, resp->lmp_subver);
+
+ lmp_subver = le16_to_cpu(resp->lmp_subver);
+ kfree_skb(skb);
+
+ /* Match a set of subver values that correspond to stock firmware,
+ * which is not compatible with standard btusb.
+ * If matched, upload an alternative firmware that does conform to
+ * standard btusb. Once that firmware is uploaded, the subver changes
+ * to a different value.
+ */
+ switch (lmp_subver) {
+ case RTL_ROM_LMP_8723A:
+ case RTL_ROM_LMP_3499:
+ return btusb_setup_rtl8723a(hdev);
+ case RTL_ROM_LMP_8723B:
+ return btusb_setup_rtl8723b(hdev, lmp_subver,
+ "rtl_bt/rtl8723b_fw.bin");
+ case RTL_ROM_LMP_8821A:
+ return btusb_setup_rtl8723b(hdev, lmp_subver,
+ "rtl_bt/rtl8821a_fw.bin");
+ case RTL_ROM_LMP_8761A:
+ return btusb_setup_rtl8723b(hdev, lmp_subver,
+ "rtl_bt/rtl8761a_fw.bin");
+ default:
+ BT_INFO("rtl: assuming no firmware upload needed.");
+ return 0;
+ }
+}
+
static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
struct intel_version *ver)
{
@@ -2776,6 +3172,9 @@ static int btusb_probe(struct usb_interface *intf,
hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
}

+ if (id->driver_info & BTUSB_REALTEK)
+ hdev->setup = btusb_setup_realtek;
+
if (id->driver_info & BTUSB_AMP) {
/* AMP controllers do not support SCO packets */
data->isoc = NULL;
--
2.1.0


2015-04-28 14:05:38

by Daniel Drake

[permalink] [raw]
Subject: Re: 答复: [PATCH v8] Bluetooth: btusb: Add Realtek 8723A/8723B/8761A/8821A support

Hi Champion,

On Mon, Apr 27, 2015 at 11:50 PM, =E9=99=88=E8=89=B3=E8=90=8D <champion_che=
[email protected]> wrote:
> Dear Daniel,
> I did not find the patches at http://git.kernel.org/, would you p=
lease send me the website address?

These patches are scheduled for inclusion in Linux 4.2, you can find them h=
ere:
http://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git

Thanks
Daniel

2015-04-28 05:50:51

by 陈艳萍

[permalink] [raw]
Subject: 答复: [PATCH v8] Bluetooth: btusb: Add Real tek 8723A/8723B/8761A/8821A support

RGVhciBEYW5pZWwsDQoJSSBkaWQgbm90IGZpbmQgdGhlIHBhdGNoZXMgYXQgaHR0cDovL2dpdC5r
ZXJuZWwub3JnLywgd291bGQgeW91IHBsZWFzZSBzZW5kIG1lIHRoZSB3ZWJzaXRlIGFkZHJlc3M/
IA0KVGhhbmtzIQ0KDQoNCkNoYW1waW9uDQpFeHQ6NjMyNQ0KDQotLS0tLemCruS7tuWOn+S7ti0t
LS0tDQrlj5Hku7bkuro6IERhbmllbCBEcmFrZSBbbWFpbHRvOmRyYWtlQGVuZGxlc3NtLmNvbV0g
DQrlj5HpgIHml7bpl7Q6IDIwMTXlubQ05pyIMTfml6UgNDoxMA0K5pS25Lu25Lq6OiBtYXJjZWxA
aG9sdG1hbm4ub3JnOyBndXN0YXZvQHBhZG92YW4ub3JnOyBqb2hhbi5oZWRiZXJnQGdtYWlsLmNv
bQ0K5oqE6YCBOiBsaW51eC1ibHVldG9vdGhAdmdlci5rZXJuZWwub3JnOyBsYXJyeS5maW5nZXJA
bHdmaW5nZXIubmV0OyDpmYjoibPokI07IGNhcmxvQGVuZGxlc3NtLmNvbQ0K5Li76aKYOiBbUEFU
Q0ggdjhdIEJsdWV0b290aDogYnR1c2I6IEFkZCBSZWFsdGVrIDg3MjNBLzg3MjNCLzg3NjFBLzg4
MjFBIHN1cHBvcnQNCg0KUmVhbHRlayBzaGlwIGEgdmFyaWV0eSBvZiBibHVldG9vdGggVVNCIGRl
dmljZXMgdGhhdCBpZGVudGlmeSB0aGVtc2VsdmVzIHdpdGggc3RhbmRhcmQgVVNCIEJsdWV0b290
aCBkZXZpY2UgY2xhc3MgdmFsdWVzLCBidXQgcmVxdWlyZSBhIHNwZWNpYWwgZHJpdmVyIHRvIGFj
dHVhbGx5IHdvcmsuIFdpdGhvdXQgdGhhdCBkcml2ZXIsIHlvdSBuZXZlciBnZXQgYW55IHNjYW4g
cmVzdWx0cy4NCg0KTW9yZSByZWNlbnRseSBob3dldmVyLCBSZWFsdGVrIGFwcGVhciB0byBoYXZl
IHdpc2VuZWQgdXAgYW5kIHNpbXBseSBwb3N0ZWQgYSBmaXJtd2FyZSB1cGRhdGUgdGhhdCBtYWtl
cyB0aGVzZSBkZXZpY2VzIGNvbXBseSB3aXRoIG5vcm1hbCBidHVzYiBwcm90b2NvbHMuIFRoZSBm
aXJtd2FyZSBuZWVkcyB0byBiZSB1cGxvYWRlZCBvbiBlYWNoIGJvb3QuDQoNCkJhc2VkIG9uIFJl
YWx0ZWsgY29kZSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9sd2Zpbmdlci9ydGw4NzIzYXVfYnQN
CignbmV3JyBicmFuY2gpLg0KDQpUaGlzIGVuYWJsZXMgYmx1ZXRvb3RoIHN1cHBvcnQgaW4gdGhl
IEdpZ2FieXRlIEJyaXggR0ItQlhCVC0yODA3IHdoaWNoIGhhcyB0aGlzIFJUTDg3MjNCRSBVU0Ig
ZGV2aWNlOg0KDQpUOiAgQnVzPTAxIExldj0wMSBQcm50PTAxIFBvcnQ9MDEgQ250PTAyIERldiM9
ICAzIFNwZD0xMiAgIE14Q2g9IDANCkQ6ICBWZXI9IDIuMTAgQ2xzPWUwKHdsY29uKSBTdWI9MDEg
UHJvdD0wMSBNeFBTPTY0ICNDZmdzPSAgMQ0KUDogIFZlbmRvcj0xM2QzIFByb2RJRD0zNDEwIFJl
dj0gMi4wMA0KUzogIE1hbnVmYWN0dXJlcj1SZWFsdGVrDQpTOiAgUHJvZHVjdD1CbHVldG9vdGgg
UmFkaW8NClM6ICBTZXJpYWxOdW1iZXI9MDBlMDRjMDAwMDAxDQpDOiogI0lmcz0gMiBDZmcjPSAx
IEF0cj1lMCBNeFB3cj01MDBtQQ0KSToqIElmIz0gMCBBbHQ9IDAgI0VQcz0gMyBDbHM9ZTAod2xj
b24pIFN1Yj0wMSBQcm90PTAxIERyaXZlcj1idHVzYg0KRTogIEFkPTgxKEkpIEF0cj0wMyhJbnQu
KSBNeFBTPSAgMTYgSXZsPTFtcw0KRTogIEFkPTAyKE8pIEF0cj0wMihCdWxrKSBNeFBTPSAgNjQg
SXZsPTBtcw0KRTogIEFkPTgyKEkpIEF0cj0wMihCdWxrKSBNeFBTPSAgNjQgSXZsPTBtcw0KSToq
IElmIz0gMSBBbHQ9IDAgI0VQcz0gMiBDbHM9ZTAod2xjb24pIFN1Yj0wMSBQcm90PTAxIERyaXZl
cj1idHVzYg0KRTogIEFkPTAzKE8pIEF0cj0wMShJc29jKSBNeFBTPSAgIDAgSXZsPTFtcw0KRTog
IEFkPTgzKEkpIEF0cj0wMShJc29jKSBNeFBTPSAgIDAgSXZsPTFtcw0KSTogIElmIz0gMSBBbHQ9
IDEgI0VQcz0gMiBDbHM9ZTAod2xjb24pIFN1Yj0wMSBQcm90PTAxIERyaXZlcj1idHVzYg0KRTog
IEFkPTAzKE8pIEF0cj0wMShJc29jKSBNeFBTPSAgIDkgSXZsPTFtcw0KRTogIEFkPTgzKEkpIEF0
cj0wMShJc29jKSBNeFBTPSAgIDkgSXZsPTFtcw0KSTogIElmIz0gMSBBbHQ9IDIgI0VQcz0gMiBD
bHM9ZTAod2xjb24pIFN1Yj0wMSBQcm90PTAxIERyaXZlcj1idHVzYg0KRTogIEFkPTAzKE8pIEF0
cj0wMShJc29jKSBNeFBTPSAgMTcgSXZsPTFtcw0KRTogIEFkPTgzKEkpIEF0cj0wMShJc29jKSBN
eFBTPSAgMTcgSXZsPTFtcw0KSTogIElmIz0gMSBBbHQ9IDMgI0VQcz0gMiBDbHM9ZTAod2xjb24p
IFN1Yj0wMSBQcm90PTAxIERyaXZlcj1idHVzYg0KRTogIEFkPTAzKE8pIEF0cj0wMShJc29jKSBN
eFBTPSAgMjUgSXZsPTFtcw0KRTogIEFkPTgzKEkpIEF0cj0wMShJc29jKSBNeFBTPSAgMjUgSXZs
PTFtcw0KSTogIElmIz0gMSBBbHQ9IDQgI0VQcz0gMiBDbHM9ZTAod2xjb24pIFN1Yj0wMSBQcm90
PTAxIERyaXZlcj1idHVzYg0KRTogIEFkPTAzKE8pIEF0cj0wMShJc29jKSBNeFBTPSAgMzMgSXZs
PTFtcw0KRTogIEFkPTgzKEkpIEF0cj0wMShJc29jKSBNeFBTPSAgMzMgSXZsPTFtcw0KSTogIElm
Iz0gMSBBbHQ9IDUgI0VQcz0gMiBDbHM9ZTAod2xjb24pIFN1Yj0wMSBQcm90PTAxIERyaXZlcj1i
dHVzYg0KRTogIEFkPTAzKE8pIEF0cj0wMShJc29jKSBNeFBTPSAgNDkgSXZsPTFtcw0KRTogIEFk
PTgzKEkpIEF0cj0wMShJc29jKSBNeFBTPSAgNDkgSXZsPTFtcw0KDQpUaGVyZSBpcyBubyBjaGFu
Z2UgdG8gdGhlIFVTQiBkZXNjcmlwdG9yIGFmdGVyIGZpcm13YXJlIHVwZGF0ZSwgaG93ZXZlciB0
aGUgdmVyc2lvbiByZWFkIGJ5IEhDSV9PUF9SRUFEX0xPQ0FMX1ZFUlNJT04gY2hhbmdlcyBmcm9t
DQoweDg3MjMgdG8gMHgzMDgzLg0KDQpUaGlzIGhhcyBhbHNvIGJlZW4gdGVzdGVkIG9uIFJUTDg3
MjNBRSBhbmQgUlRMODgyMUFFLiBTdXBwb3J0IGZvciBSVEw4NzYxQSBoYXMgYWxzbyBiZWVuIGFk
ZGVkLCBidXQgdGhhdCBpcyB1bnRlc3RlZC4NCg0KU2lnbmVkLW9mZi1ieTogRGFuaWVsIERyYWtl
IDxkcmFrZUBlbmRsZXNzbS5jb20+DQpUZXN0ZWQtYnk6IExhcnJ5IEZpbmdlciA8TGFycnkuRmlu
Z2VyQGx3ZmluZ2VyLm5ldD4NCi0tLQ0KIGRyaXZlcnMvYmx1ZXRvb3RoL2J0dXNiLmMgfCAzOTkg
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKw0KIDEgZmlsZSBj
aGFuZ2VkLCAzOTkgaW5zZXJ0aW9ucygrKQ0KDQp2ODoNCiAtIG1pbm9yIGNsZWFudXBzDQogLSBy
ZW1vdmUgc3VzcGVuZC9yZXN1bWUgc3VwcG9ydCwgdGhpcyB3aWxsIGJlIHN1Ym1pdHRlZCBsYXRl
ciwgc2VwYXJhdGVseQ0KDQp2NzoNCiAtIFJlYmFzZSBvbiBibHVldG9vdGgtbmV4dA0KIC0gQWRk
IHN1c3BlbmQvcmVzdW1lIHN1cHBvcnQNCg0KdjY6DQogLSBSZWFsbHkgYWRkIGZpcm13YXJlIGxv
ZyBtZXNzYWdlLg0KDQp2NToNCiAtIGxvZyBmaXJtd2FyZSBmaWxlbmFtZSBiZWZvcmUgbG9hZGlu
ZyBpdA0KIC0gdGhpcyBoYXMgcGFzc2VkIHRlc3RpbmcgZnJvbSBMYXJyeSBhbmQgZnJpZW5kcw0K
DQp2NDoNCiAtIFNpbXBsaWZ5IElEIG1hdGNoaW5nOiBtYXRjaCBqdXN0IHRoZSBSZWFsdGVrIHZl
bmRvciwgYW5kIHRoZSBub24tUmVhbHRlaw0KICAgZGV2aWNlIElEcy4gU3BlY2lmaWMgY2hpcCBk
ZXRlY3Rpb24gaXMgdGhlbiBkb25lIHdpdGggUkVBRF9MT0NBTF9WRVJTSU9OLg0KIC0gRW5kaWFu
bmVzcyBmaXhlcw0KIC0gQWRkcmVzc2VkIG90aGVyIHJldmlldyBjb21tZW50cw0KDQp2MzoNCiAt
IFJlbW92ZWQgc3VwcG9ydCBmb3IgZGV2aWNlcyB3aGVyZSB3ZSBkb24ndCBoYXZlIGZpcm13YXJl
DQogLSBEaXZpZGUgODcyM0EvODcyM0IgY29kZXBhdGhzIGJhc2VkIG9uIGRyaXZlcl9pbmZvIGNv
bnN0YW50DQogLSBBZGRlZCBtb3JlIGRldmljZSBJRHMgZnJvbSBsYXRlc3QgUmVhbHRlayBjb2Rl
DQogLSBBZGRyZXNzZWQgbWlub3IgcmV2aWV3IGNvbW1lbnRzDQogLSBSZW5hbWUgUlRLIC0tPiBS
VEwNCg0KdjI6DQogLSBzaGFyZSBtYWluIGJsYWNrbGlzdCB0YWJsZSB3aXRoIG90aGVyIGRldmlj
ZXMNCiAtIGVwYXRjaCB0YWJsZSBwYXJzaW5nIGVuZGlhbi9hbGlnbm1lbnQgZml4ZXMNCiAtIEJU
X0lORk8gbWVzc2FnZSB0byBpbmZvcm0gdXNlcg0KIC0gYWRkZWQgbWlzc2luZyBrbWFsbG9jIGVy
cm9yIGNoZWNrDQogLSBmaXhlZCBza2IgbGVhaw0KIC0gc3R5bGUgZml4ZXMNCg0KZGlmZiAtLWdp
dCBhL2RyaXZlcnMvYmx1ZXRvb3RoL2J0dXNiLmMgYi9kcml2ZXJzL2JsdWV0b290aC9idHVzYi5j
IGluZGV4IGRlN2IyMzYuLjg0Zjk5ODUgMTAwNjQ0DQotLS0gYS9kcml2ZXJzL2JsdWV0b290aC9i
dHVzYi5jDQorKysgYi9kcml2ZXJzL2JsdWV0b290aC9idHVzYi5jDQpAQCAtMjQsNiArMjQsNyBA
QA0KICNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4NCiAjaW5jbHVkZSA8bGludXgvdXNiLmg+DQog
I2luY2x1ZGUgPGxpbnV4L2Zpcm13YXJlLmg+DQorI2luY2x1ZGUgPGFzbS91bmFsaWduZWQuaD4N
CiANCiAjaW5jbHVkZSA8bmV0L2JsdWV0b290aC9ibHVldG9vdGguaD4NCiAjaW5jbHVkZSA8bmV0
L2JsdWV0b290aC9oY2lfY29yZS5oPg0KQEAgLTU3LDYgKzU4LDcgQEAgc3RhdGljIHN0cnVjdCB1
c2JfZHJpdmVyIGJ0dXNiX2RyaXZlcjsNCiAjZGVmaW5lIEJUVVNCX0FNUAkJMHg0MDAwDQogI2Rl
ZmluZSBCVFVTQl9RQ0FfUk9NRQkJMHg4MDAwDQogI2RlZmluZSBCVFVTQl9CQ01fQVBQTEUJCTB4
MTAwMDANCisjZGVmaW5lIEJUVVNCX1JFQUxURUsJCTB4MjAwMDANCiANCiBzdGF0aWMgY29uc3Qg
c3RydWN0IHVzYl9kZXZpY2VfaWQgYnR1c2JfdGFibGVbXSA9IHsNCiAJLyogR2VuZXJpYyBCbHVl
dG9vdGggVVNCIGRldmljZSAqLw0KQEAgLTI4OCw2ICsyOTAsMjggQEAgc3RhdGljIGNvbnN0IHN0
cnVjdCB1c2JfZGV2aWNlX2lkIGJsYWNrbGlzdF90YWJsZVtdID0gew0KIAl7IFVTQl9WRU5ET1Jf
QU5EX0lOVEVSRkFDRV9JTkZPKDB4ODA4NywgMHhlMCwgMHgwMSwgMHgwMSksDQogCSAgLmRyaXZl
cl9pbmZvID0gQlRVU0JfSUdOT1JFIH0sDQogDQorCS8qIFJlYWx0ZWsgQmx1ZXRvb3RoIGRldmlj
ZXMgKi8NCisJeyBVU0JfVkVORE9SX0FORF9JTlRFUkZBQ0VfSU5GTygweDBiZGEsIDB4ZTAsIDB4
MDEsIDB4MDEpLA0KKwkgIC5kcml2ZXJfaW5mbyA9IEJUVVNCX1JFQUxURUsgfSwNCisNCisJLyog
QWRkaXRpb25hbCBSZWFsdGVrIDg3MjNBRSBCbHVldG9vdGggZGV2aWNlcyAqLw0KKwl7IFVTQl9E
RVZJQ0UoMHgwOTMwLCAweDAyMWQpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9SRUFMVEVLIH0sDQor
CXsgVVNCX0RFVklDRSgweDEzZDMsIDB4MzM5NCksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX1JFQUxU
RUsgfSwNCisNCisJLyogQWRkaXRpb25hbCBSZWFsdGVrIDg3MjNCRSBCbHVldG9vdGggZGV2aWNl
cyAqLw0KKwl7IFVTQl9ERVZJQ0UoMHgwNDg5LCAweGUwODUpLCAuZHJpdmVyX2luZm8gPSBCVFVT
Ql9SRUFMVEVLIH0sDQorCXsgVVNCX0RFVklDRSgweDA0ODksIDB4ZTA4YiksIC5kcml2ZXJfaW5m
byA9IEJUVVNCX1JFQUxURUsgfSwNCisJeyBVU0JfREVWSUNFKDB4MTNkMywgMHgzNDEwKSwgLmRy
aXZlcl9pbmZvID0gQlRVU0JfUkVBTFRFSyB9LA0KKwl7IFVTQl9ERVZJQ0UoMHgxM2QzLCAweDM0
MTYpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9SRUFMVEVLIH0sDQorCXsgVVNCX0RFVklDRSgweDEz
ZDMsIDB4MzQ1OSksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX1JFQUxURUsgfSwNCisNCisJLyogQWRk
aXRpb25hbCBSZWFsdGVrIDg4MjFBRSBCbHVldG9vdGggZGV2aWNlcyAqLw0KKwl7IFVTQl9ERVZJ
Q0UoMHgwYjA1LCAweDE3ZGMpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9SRUFMVEVLIH0sDQorCXsg
VVNCX0RFVklDRSgweDEzZDMsIDB4MzQxNCksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX1JFQUxURUsg
fSwNCisJeyBVU0JfREVWSUNFKDB4MTNkMywgMHgzNDU4KSwgLmRyaXZlcl9pbmZvID0gQlRVU0Jf
UkVBTFRFSyB9LA0KKwl7IFVTQl9ERVZJQ0UoMHgxM2QzLCAweDM0NjEpLCAuZHJpdmVyX2luZm8g
PSBCVFVTQl9SRUFMVEVLIH0sDQorCXsgVVNCX0RFVklDRSgweDEzZDMsIDB4MzQ2MiksIC5kcml2
ZXJfaW5mbyA9IEJUVVNCX1JFQUxURUsgfSwNCisNCiAJeyB9CS8qIFRlcm1pbmF0aW5nIGVudHJ5
ICovDQogfTsNCiANCkBAIC0xMzQ1LDYgKzEzNjksMzc4IEBAIHN0YXRpYyBpbnQgYnR1c2Jfc2V0
dXBfY3NyKHN0cnVjdCBoY2lfZGV2ICpoZGV2KQ0KIAlyZXR1cm4gcmV0Ow0KIH0NCiANCisjZGVm
aW5lIFJUTF9GUkFHX0xFTiAyNTINCisNCitzdHJ1Y3QgcnRsX2Rvd25sb2FkX2NtZCB7DQorCV9f
dTggaW5kZXg7DQorCV9fdTggZGF0YVtSVExfRlJBR19MRU5dOw0KK30gX19wYWNrZWQ7DQorDQor
c3RydWN0IHJ0bF9kb3dubG9hZF9yZXNwb25zZSB7DQorCV9fdTggc3RhdHVzOw0KKwlfX3U4IGlu
ZGV4Ow0KK30gX19wYWNrZWQ7DQorDQorc3RydWN0IHJ0bF9yb21fdmVyc2lvbl9ldnQgew0KKwlf
X3U4IHN0YXR1czsNCisJX191OCB2ZXJzaW9uOw0KK30gX19wYWNrZWQ7DQorDQorc3RydWN0IHJ0
bF9lcGF0Y2hfaGVhZGVyIHsNCisJX191OCBzaWduYXR1cmVbOF07DQorCV9fbGUzMiBmd192ZXJz
aW9uOw0KKwlfX2xlMTYgbnVtX3BhdGNoZXM7DQorfSBfX3BhY2tlZDsNCisNCisjZGVmaW5lIFJU
TF9FUEFUQ0hfU0lHTkFUVVJFCSJSZWFsdGVjaCINCisjZGVmaW5lIFJUTF9ST01fTE1QXzM0OTkJ
MHgzNDk5DQorI2RlZmluZSBSVExfUk9NX0xNUF84NzIzQQkweDEyMDANCisjZGVmaW5lIFJUTF9S
T01fTE1QXzg3MjNCCTB4ODcyMw0KKyNkZWZpbmUgUlRMX1JPTV9MTVBfODgyMUEJMHg4ODIxDQor
I2RlZmluZSBSVExfUk9NX0xNUF84NzYxQQkweDg3NjENCisNCitzdGF0aWMgaW50IHJ0bF9yZWFk
X3JvbV92ZXJzaW9uKHN0cnVjdCBoY2lfZGV2ICpoZGV2LCB1OCAqdmVyc2lvbikgew0KKwlzdHJ1
Y3QgcnRsX3JvbV92ZXJzaW9uX2V2dCAqcm9tX3ZlcnNpb247DQorCXN0cnVjdCBza19idWZmICpz
a2I7DQorCWludCByZXQ7DQorDQorCS8qIFJlYWQgUlRMIFJPTSB2ZXJzaW9uIGNvbW1hbmQgKi8N
CisJc2tiID0gX19oY2lfY21kX3N5bmMoaGRldiwgMHhmYzZkLCAwLCBOVUxMLCBIQ0lfSU5JVF9U
SU1FT1VUKTsNCisJaWYgKElTX0VSUihza2IpKSB7DQorCQlCVF9FUlIoIiVzOiBSZWFkIFJPTSB2
ZXJzaW9uIGZhaWxlZCAoJWxkKSIsDQorCQkgICAgICAgaGRldi0+bmFtZSwgUFRSX0VSUihza2Ip
KTsNCisJCXJldHVybiBQVFJfRVJSKHNrYik7DQorCX0NCisNCisJaWYgKHNrYi0+bGVuICE9IHNp
emVvZigqcm9tX3ZlcnNpb24pKSB7DQorCQlCVF9FUlIoIiVzOiBSVEwgdmVyc2lvbiBldmVudCBs
ZW5ndGggbWlzbWF0Y2giLCBoZGV2LT5uYW1lKTsNCisJCWtmcmVlX3NrYihza2IpOw0KKwkJcmV0
dXJuIC1FSU87DQorCX0NCisNCisJcm9tX3ZlcnNpb24gPSAoc3RydWN0IHJ0bF9yb21fdmVyc2lv
bl9ldnQgKilza2ItPmRhdGE7DQorCUJUX0lORk8oIiVzOiByb21fdmVyc2lvbiBzdGF0dXM9JXgg
dmVyc2lvbj0leCIsDQorCQloZGV2LT5uYW1lLCByb21fdmVyc2lvbi0+c3RhdHVzLCByb21fdmVy
c2lvbi0+dmVyc2lvbik7DQorDQorCXJldCA9IHJvbV92ZXJzaW9uLT5zdGF0dXM7DQorCWlmIChy
ZXQgPT0gMCkNCisJCSp2ZXJzaW9uID0gcm9tX3ZlcnNpb24tPnZlcnNpb247DQorDQorCWtmcmVl
X3NrYihza2IpOw0KKwlyZXR1cm4gcmV0Ow0KK30NCisNCitzdGF0aWMgaW50IHJ0bDg3MjNiX3Bh
cnNlX2Zpcm13YXJlKHN0cnVjdCBoY2lfZGV2ICpoZGV2LCB1MTYgbG1wX3N1YnZlciwNCisJCQkJ
ICAgY29uc3Qgc3RydWN0IGZpcm13YXJlICpmdywNCisJCQkJICAgdW5zaWduZWQgY2hhciAqKl9i
dWYpDQorew0KKwljb25zdCB1OCBleHRlbnNpb25fc2lnW10gPSB7IDB4NTEsIDB4MDQsIDB4ZmQs
IDB4NzcgfTsNCisJc3RydWN0IHJ0bF9lcGF0Y2hfaGVhZGVyICplcGF0Y2hfaW5mbzsNCisJdW5z
aWduZWQgY2hhciAqYnVmOw0KKwlpbnQgaSwgcmV0LCBsZW47DQorCXNpemVfdCBtaW5fc2l6ZTsN
CisJdTggb3Bjb2RlLCBsZW5ndGgsIGRhdGEsIHJvbV92ZXJzaW9uID0gMDsNCisJaW50IHByb2pl
Y3RfaWQgPSAtMTsNCisJY29uc3QgdW5zaWduZWQgY2hhciAqZndwdHIsICpjaGlwX2lkX2Jhc2U7
DQorCWNvbnN0IHVuc2lnbmVkIGNoYXIgKnBhdGNoX2xlbmd0aF9iYXNlLCAqcGF0Y2hfb2Zmc2V0
X2Jhc2U7DQorCXUzMiBwYXRjaF9vZmZzZXQgPSAwOw0KKwl1MTYgcGF0Y2hfbGVuZ3RoLCBudW1f
cGF0Y2hlczsNCisJY29uc3QgdTE2IHByb2plY3RfaWRfdG9fbG1wX3N1YnZlcltdID0gew0KKwkJ
UlRMX1JPTV9MTVBfODcyM0EsDQorCQlSVExfUk9NX0xNUF84NzIzQiwNCisJCVJUTF9ST01fTE1Q
Xzg4MjFBLA0KKwkJUlRMX1JPTV9MTVBfODc2MUENCisJfTsNCisNCisJcmV0ID0gcnRsX3JlYWRf
cm9tX3ZlcnNpb24oaGRldiwgJnJvbV92ZXJzaW9uKTsNCisJaWYgKHJldCkNCisJCXJldHVybiAt
YnRfdG9fZXJybm8ocmV0KTsNCisNCisJbWluX3NpemUgPSBzaXplb2Yoc3RydWN0IHJ0bF9lcGF0
Y2hfaGVhZGVyKSArIHNpemVvZihleHRlbnNpb25fc2lnKSArIDM7DQorCWlmIChmdy0+c2l6ZSA8
IG1pbl9zaXplKQ0KKwkJcmV0dXJuIC1FSU5WQUw7DQorDQorCWZ3cHRyID0gZnctPmRhdGEgKyBm
dy0+c2l6ZSAtIHNpemVvZihleHRlbnNpb25fc2lnKTsNCisJaWYgKG1lbWNtcChmd3B0ciwgZXh0
ZW5zaW9uX3NpZywgc2l6ZW9mKGV4dGVuc2lvbl9zaWcpKSAhPSAwKSB7DQorCQlCVF9FUlIoIiVz
OiBleHRlbnNpb24gc2VjdGlvbiBzaWduYXR1cmUgbWlzbWF0Y2giLCBoZGV2LT5uYW1lKTsNCisJ
CXJldHVybiAtRUlOVkFMOw0KKwl9DQorDQorCS8qIExvb3AgZnJvbSB0aGUgZW5kIG9mIHRoZSBm
aXJtd2FyZSBwYXJzaW5nIGluc3RydWN0aW9ucywgdW50aWwNCisJICogd2UgZmluZCBhbiBpbnN0
cnVjdGlvbiB0aGF0IGlkZW50aWZpZXMgdGhlICJwcm9qZWN0IElEIiBmb3IgdGhlDQorCSAqIGhh
cmR3YXJlIHN1cHBvcnRlZCBieSB0aGlzIGZpcndtYXJlIGZpbGUuDQorCSAqIE9uY2Ugd2UgaGF2
ZSB0aGF0LCB3ZSBkb3VibGUtY2hlY2sgdGhhdCB0aGF0IHByb2plY3RfaWQgaXMgc3VpdGFibGUN
CisJICogZm9yIHRoZSBoYXJkd2FyZSB3ZSBhcmUgd29ya2luZyB3aXRoLg0KKwkgKi8NCisJd2hp
bGUgKGZ3cHRyID49IGZ3LT5kYXRhICsgKHNpemVvZihzdHJ1Y3QgcnRsX2VwYXRjaF9oZWFkZXIp
ICsgMykpIHsNCisJCW9wY29kZSA9ICotLWZ3cHRyOw0KKwkJbGVuZ3RoID0gKi0tZndwdHI7DQor
CQlkYXRhID0gKi0tZndwdHI7DQorDQorCQlCVF9EQkcoImNoZWNrIG9wPSV4IGxlbj0leCBkYXRh
PSV4Iiwgb3Bjb2RlLCBsZW5ndGgsIGRhdGEpOw0KKw0KKwkJaWYgKG9wY29kZSA9PSAweGZmKSAv
KiBFT0YgKi8NCisJCQlicmVhazsNCisNCisJCWlmIChsZW5ndGggPT0gMCkgew0KKwkJCUJUX0VS
UigiJXM6IGZvdW5kIGluc3RydWN0aW9uIHdpdGggbGVuZ3RoIDAiLA0KKwkJCSAgICAgICBoZGV2
LT5uYW1lKTsNCisJCQlyZXR1cm4gLUVJTlZBTDsNCisJCX0NCisNCisJCWlmIChvcGNvZGUgPT0g
MCAmJiBsZW5ndGggPT0gMSkgew0KKwkJCXByb2plY3RfaWQgPSBkYXRhOw0KKwkJCWJyZWFrOw0K
KwkJfQ0KKw0KKwkJZndwdHIgLT0gbGVuZ3RoOw0KKwl9DQorDQorCWlmIChwcm9qZWN0X2lkIDwg
MCkgew0KKwkJQlRfRVJSKCIlczogZmFpbGVkIHRvIGZpbmQgdmVyc2lvbiBpbnN0cnVjdGlvbiIs
IGhkZXYtPm5hbWUpOw0KKwkJcmV0dXJuIC1FSU5WQUw7DQorCX0NCisNCisJaWYgKHByb2plY3Rf
aWQgPiBBUlJBWV9TSVpFKHByb2plY3RfaWRfdG9fbG1wX3N1YnZlcikpIHsNCisJCUJUX0VSUigi
JXM6IHVua25vd24gcHJvamVjdCBpZCAlZCIsIGhkZXYtPm5hbWUsIHByb2plY3RfaWQpOw0KKwkJ
cmV0dXJuIC1FSU5WQUw7DQorCX0NCisNCisJaWYgKGxtcF9zdWJ2ZXIgIT0gcHJvamVjdF9pZF90
b19sbXBfc3VidmVyW3Byb2plY3RfaWRdKSB7DQorCQlCVF9FUlIoIiVzOiBmaXJtd2FyZSBpcyBm
b3IgJXggYnV0IHRoaXMgaXMgYSAleCIsIGhkZXYtPm5hbWUsDQorCQkgICAgICAgcHJvamVjdF9p
ZF90b19sbXBfc3VidmVyW3Byb2plY3RfaWRdLCBsbXBfc3VidmVyKTsNCisJCXJldHVybiAtRUlO
VkFMOw0KKwl9DQorDQorCWVwYXRjaF9pbmZvID0gKHN0cnVjdCBydGxfZXBhdGNoX2hlYWRlciAq
KWZ3LT5kYXRhOw0KKwlpZiAobWVtY21wKGVwYXRjaF9pbmZvLT5zaWduYXR1cmUsIFJUTF9FUEFU
Q0hfU0lHTkFUVVJFLCA4KSAhPSAwKSB7DQorCQlCVF9FUlIoIiVzOiBiYWQgRVBBVENIIHNpZ25h
dHVyZSIsIGhkZXYtPm5hbWUpOw0KKwkJcmV0dXJuIC1FSU5WQUw7DQorCX0NCisNCisJbnVtX3Bh
dGNoZXMgPSBsZTE2X3RvX2NwdShlcGF0Y2hfaW5mby0+bnVtX3BhdGNoZXMpOw0KKwlCVF9EQkco
ImZ3X3ZlcnNpb249JXgsIG51bV9wYXRjaGVzPSVkIiwNCisJICAgICAgIGxlMzJfdG9fY3B1KGVw
YXRjaF9pbmZvLT5md192ZXJzaW9uKSwgbnVtX3BhdGNoZXMpOw0KKw0KKwkvKiBBZnRlciB0aGUg
cnRsX2VwYXRjaF9oZWFkZXIgdGhlcmUgaXMgYSBmdW5reSBwYXRjaCBtZXRhZGF0YSBzZWN0aW9u
Lg0KKwkgKiBBc3N1bWluZyAyIHBhdGNoZXMsIHRoZSBsYXlvdXQgaXM6DQorCSAqIENoaXBJRDEg
Q2hpcElEMiBQYXRjaExlbmd0aDEgUGF0Y2hMZW5ndGgyIFBhdGNoT2Zmc2V0MSBQYXRjaE9mZnNl
dDINCisJICoNCisJICogRmluZCB0aGUgcmlnaHQgcGF0Y2ggZm9yIHRoaXMgY2hpcC4NCisJICov
DQorCW1pbl9zaXplICs9IDggKiBudW1fcGF0Y2hlczsNCisJaWYgKGZ3LT5zaXplIDwgbWluX3Np
emUpDQorCQlyZXR1cm4gLUVJTlZBTDsNCisNCisJY2hpcF9pZF9iYXNlID0gZnctPmRhdGEgKyBz
aXplb2Yoc3RydWN0IHJ0bF9lcGF0Y2hfaGVhZGVyKTsNCisJcGF0Y2hfbGVuZ3RoX2Jhc2UgPSBj
aGlwX2lkX2Jhc2UgKyAoc2l6ZW9mKHUxNikgKiBudW1fcGF0Y2hlcyk7DQorCXBhdGNoX29mZnNl
dF9iYXNlID0gcGF0Y2hfbGVuZ3RoX2Jhc2UgKyAoc2l6ZW9mKHUxNikgKiBudW1fcGF0Y2hlcyk7
DQorCWZvciAoaSA9IDA7IGkgPCBudW1fcGF0Y2hlczsgaSsrKSB7DQorCQl1MTYgY2hpcF9pZCA9
IGdldF91bmFsaWduZWRfbGUxNihjaGlwX2lkX2Jhc2UgKw0KKwkJCQkJCSAoaSAqIHNpemVvZih1
MTYpKSk7DQorCQlpZiAoY2hpcF9pZCA9PSByb21fdmVyc2lvbiArIDEpIHsNCisJCQlwYXRjaF9s
ZW5ndGggPSBnZXRfdW5hbGlnbmVkX2xlMTYocGF0Y2hfbGVuZ3RoX2Jhc2UgKw0KKwkJCQkJCQkg
IChpICogc2l6ZW9mKHUxNikpKTsNCisJCQlwYXRjaF9vZmZzZXQgPSBnZXRfdW5hbGlnbmVkX2xl
MzIocGF0Y2hfb2Zmc2V0X2Jhc2UgKw0KKwkJCQkJCQkgIChpICogc2l6ZW9mKHUzMikpKTsNCisJ
CQlicmVhazsNCisJCX0NCisJfQ0KKw0KKwlpZiAoIXBhdGNoX29mZnNldCkgew0KKwkJQlRfRVJS
KCIlczogZGlkbid0IGZpbmQgcGF0Y2ggZm9yIGNoaXAgaWQgJWQiLA0KKwkJICAgICAgIGhkZXYt
Pm5hbWUsIHJvbV92ZXJzaW9uKTsNCisJCXJldHVybiAtRUlOVkFMOw0KKwl9DQorDQorCUJUX0RC
RygibGVuZ3RoPSV4IG9mZnNldD0leCBpbmRleCAlZCIsIHBhdGNoX2xlbmd0aCwgcGF0Y2hfb2Zm
c2V0LCBpKTsNCisJbWluX3NpemUgPSBwYXRjaF9vZmZzZXQgKyBwYXRjaF9sZW5ndGg7DQorCWlm
IChmdy0+c2l6ZSA8IG1pbl9zaXplKQ0KKwkJcmV0dXJuIC1FSU5WQUw7DQorDQorCS8qIENvcHkg
dGhlIGZpcm13YXJlIGludG8gYSBuZXcgYnVmZmVyIGFuZCB3cml0ZSB0aGUgdmVyc2lvbiBhdA0K
KwkgKiB0aGUgZW5kLg0KKwkgKi8NCisJbGVuID0gcGF0Y2hfbGVuZ3RoOw0KKwlidWYgPSBrbWVt
ZHVwKGZ3LT5kYXRhICsgcGF0Y2hfb2Zmc2V0LCBwYXRjaF9sZW5ndGgsIEdGUF9LRVJORUwpOw0K
KwlpZiAoIWJ1ZikNCisJCXJldHVybiAtRU5PTUVNOw0KKw0KKwltZW1jcHkoYnVmICsgcGF0Y2hf
bGVuZ3RoIC0gNCwgJmVwYXRjaF9pbmZvLT5md192ZXJzaW9uLCA0KTsNCisNCisJKl9idWYgPSBi
dWY7DQorCXJldHVybiBsZW47DQorfQ0KKw0KK3N0YXRpYyBpbnQgcnRsX2Rvd25sb2FkX2Zpcm13
YXJlKHN0cnVjdCBoY2lfZGV2ICpoZGV2LA0KKwkJCQkgY29uc3QgdW5zaWduZWQgY2hhciAqZGF0
YSwgaW50IGZ3X2xlbikgew0KKwlzdHJ1Y3QgcnRsX2Rvd25sb2FkX2NtZCAqZGxfY21kOw0KKwlp
bnQgZnJhZ19udW0gPSBmd19sZW4gLyBSVExfRlJBR19MRU4gKyAxOw0KKwlpbnQgZnJhZ19sZW4g
PSBSVExfRlJBR19MRU47DQorCWludCByZXQgPSAwOw0KKwlpbnQgaTsNCisNCisJZGxfY21kID0g
a21hbGxvYyhzaXplb2Yoc3RydWN0IHJ0bF9kb3dubG9hZF9jbWQpLCBHRlBfS0VSTkVMKTsNCisJ
aWYgKCFkbF9jbWQpDQorCQlyZXR1cm4gLUVOT01FTTsNCisNCisJZm9yIChpID0gMDsgaSA8IGZy
YWdfbnVtOyBpKyspIHsNCisJCXN0cnVjdCBydGxfZG93bmxvYWRfcmVzcG9uc2UgKmRsX3Jlc3A7
DQorCQlzdHJ1Y3Qgc2tfYnVmZiAqc2tiOw0KKw0KKwkJQlRfREJHKCJkb3dubG9hZCBmdyAoJWQv
JWQpIiwgaSwgZnJhZ19udW0pOw0KKw0KKwkJZGxfY21kLT5pbmRleCA9IGk7DQorCQlpZiAoaSA9
PSAoZnJhZ19udW0gLSAxKSkgew0KKwkJCWRsX2NtZC0+aW5kZXggfD0gMHg4MDsgLyogZGF0YSBl
bmQgKi8NCisJCQlmcmFnX2xlbiA9IGZ3X2xlbiAlIFJUTF9GUkFHX0xFTjsNCisJCX0NCisJCW1l
bWNweShkbF9jbWQtPmRhdGEsIGRhdGEsIGZyYWdfbGVuKTsNCisNCisJCS8qIFNlbmQgZG93bmxv
YWQgY29tbWFuZCAqLw0KKwkJc2tiID0gX19oY2lfY21kX3N5bmMoaGRldiwgMHhmYzIwLCBmcmFn
X2xlbiArIDEsIGRsX2NtZCwNCisJCQkJICAgICBIQ0lfSU5JVF9USU1FT1VUKTsNCisJCWlmIChJ
U19FUlIoc2tiKSkgew0KKwkJCUJUX0VSUigiJXM6IGRvd25sb2FkIGZ3IGNvbW1hbmQgZmFpbGVk
ICglbGQpIiwNCisJCQkgICAgICAgaGRldi0+bmFtZSwgUFRSX0VSUihza2IpKTsNCisJCQlyZXQg
PSAtUFRSX0VSUihza2IpOw0KKwkJCWdvdG8gb3V0Ow0KKwkJfQ0KKw0KKwkJaWYgKHNrYi0+bGVu
ICE9IHNpemVvZigqZGxfcmVzcCkpIHsNCisJCQlCVF9FUlIoIiVzOiBkb3dubG9hZCBmdyBldmVu
dCBsZW5ndGggbWlzbWF0Y2giLA0KKwkJCSAgICAgICBoZGV2LT5uYW1lKTsNCisJCQlrZnJlZV9z
a2Ioc2tiKTsNCisJCQlyZXQgPSAtRUlPOw0KKwkJCWdvdG8gb3V0Ow0KKwkJfQ0KKw0KKwkJZGxf
cmVzcCA9IChzdHJ1Y3QgcnRsX2Rvd25sb2FkX3Jlc3BvbnNlICopc2tiLT5kYXRhOw0KKwkJaWYg
KGRsX3Jlc3AtPnN0YXR1cyAhPSAwKSB7DQorCQkJa2ZyZWVfc2tiKHNrYik7DQorCQkJcmV0ID0g
YnRfdG9fZXJybm8oZGxfcmVzcC0+c3RhdHVzKTsNCisJCQlnb3RvIG91dDsNCisJCX0NCisNCisJ
CWtmcmVlX3NrYihza2IpOw0KKwkJZGF0YSArPSBSVExfRlJBR19MRU47DQorCX0NCisNCitvdXQ6
DQorCWtmcmVlKGRsX2NtZCk7DQorCXJldHVybiByZXQ7DQorfQ0KKw0KK3N0YXRpYyBpbnQgYnR1
c2Jfc2V0dXBfcnRsODcyM2Eoc3RydWN0IGhjaV9kZXYgKmhkZXYpIHsNCisJc3RydWN0IGJ0dXNi
X2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoJmhkZXYtPmRldik7DQorCXN0cnVjdCB1c2Jf
ZGV2aWNlICp1ZGV2ID0gaW50ZXJmYWNlX3RvX3VzYmRldihkYXRhLT5pbnRmKTsNCisJY29uc3Qg
c3RydWN0IGZpcm13YXJlICpmdzsNCisJaW50IHJldDsNCisNCisJQlRfSU5GTygiJXM6IHJ0bDog
bG9hZGluZyBydGxfYnQvcnRsODcyM2FfZncuYmluIiwgaGRldi0+bmFtZSk7DQorCXJldCA9IHJl
cXVlc3RfZmlybXdhcmUoJmZ3LCAicnRsX2J0L3J0bDg3MjNhX2Z3LmJpbiIsICZ1ZGV2LT5kZXYp
Ow0KKwlpZiAocmV0IDwgMCkgew0KKwkJQlRfRVJSKCIlczogRmFpbGVkIHRvIGxvYWQgcnRsX2J0
L3J0bDg3MjNhX2Z3LmJpbiIsIGhkZXYtPm5hbWUpOw0KKwkJcmV0dXJuIHJldDsNCisJfQ0KKw0K
KwlpZiAoZnctPnNpemUgPCA4KSB7DQorCQlyZXQgPSAtRUlOVkFMOw0KKwkJZ290byBvdXQ7DQor
CX0NCisNCisJLyogQ2hlY2sgdGhhdCB0aGUgZmlybXdhcmUgZG9lc24ndCBoYXZlIHRoZSBlcGF0
Y2ggc2lnbmF0dXJlDQorCSAqICh3aGljaCBpcyBvbmx5IGZvciBSVEw4NzIzQiBhbmQgbmV3ZXIp
Lg0KKwkgKi8NCisJaWYgKCFtZW1jbXAoZnctPmRhdGEsIFJUTF9FUEFUQ0hfU0lHTkFUVVJFLCA4
KSkgew0KKwkJQlRfRVJSKCIlczogdW5leHBlY3RlZCBFUEFUQ0ggc2lnbmF0dXJlISIsIGhkZXYt
Pm5hbWUpOw0KKwkJcmV0ID0gLUVJTlZBTDsNCisJCWdvdG8gb3V0Ow0KKwl9DQorDQorCXJldCA9
IHJ0bF9kb3dubG9hZF9maXJtd2FyZShoZGV2LCBmdy0+ZGF0YSwgZnctPnNpemUpOw0KKw0KK291
dDoNCisJcmVsZWFzZV9maXJtd2FyZShmdyk7DQorCXJldHVybiByZXQ7DQorfQ0KKw0KK3N0YXRp
YyBpbnQgYnR1c2Jfc2V0dXBfcnRsODcyM2Ioc3RydWN0IGhjaV9kZXYgKmhkZXYsIHUxNiBsbXBf
c3VidmVyLA0KKwkJCQljb25zdCBjaGFyICpmd19uYW1lKQ0KK3sNCisJc3RydWN0IGJ0dXNiX2Rh
dGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoJmhkZXYtPmRldik7DQorCXN0cnVjdCB1c2JfZGV2
aWNlICp1ZGV2ID0gaW50ZXJmYWNlX3RvX3VzYmRldihkYXRhLT5pbnRmKTsNCisJdW5zaWduZWQg
Y2hhciAqZndfZGF0YSA9IE5VTEw7DQorCWNvbnN0IHN0cnVjdCBmaXJtd2FyZSAqZnc7DQorCWlu
dCByZXQ7DQorDQorCUJUX0lORk8oIiVzOiBydGw6IGxvYWRpbmcgJXMiLCBoZGV2LT5uYW1lLCBm
d19uYW1lKTsNCisJcmV0ID0gcmVxdWVzdF9maXJtd2FyZSgmZncsIGZ3X25hbWUsICZ1ZGV2LT5k
ZXYpOw0KKwlpZiAocmV0IDwgMCkgew0KKwkJQlRfRVJSKCIlczogRmFpbGVkIHRvIGxvYWQgJXMi
LCBoZGV2LT5uYW1lLCBmd19uYW1lKTsNCisJCXJldHVybiByZXQ7DQorCX0NCisNCisJcmV0ID0g
cnRsODcyM2JfcGFyc2VfZmlybXdhcmUoaGRldiwgbG1wX3N1YnZlciwgZncsICZmd19kYXRhKTsN
CisJaWYgKHJldCA8IDApDQorCQlnb3RvIG91dDsNCisNCisJcmV0ID0gcnRsX2Rvd25sb2FkX2Zp
cm13YXJlKGhkZXYsIGZ3X2RhdGEsIHJldCk7DQorCWtmcmVlKGZ3X2RhdGEpOw0KKwlpZiAocmV0
IDwgMCkNCisJCWdvdG8gb3V0Ow0KKw0KK291dDoNCisJcmVsZWFzZV9maXJtd2FyZShmdyk7DQor
CXJldHVybiByZXQ7DQorfQ0KKw0KK3N0YXRpYyBpbnQgYnR1c2Jfc2V0dXBfcmVhbHRlayhzdHJ1
Y3QgaGNpX2RldiAqaGRldikgew0KKwlzdHJ1Y3Qgc2tfYnVmZiAqc2tiOw0KKwlzdHJ1Y3QgaGNp
X3JwX3JlYWRfbG9jYWxfdmVyc2lvbiAqcmVzcDsNCisJdTE2IGxtcF9zdWJ2ZXI7DQorDQorCXNr
YiA9IGJ0dXNiX3JlYWRfbG9jYWxfdmVyc2lvbihoZGV2KTsNCisJaWYgKElTX0VSUihza2IpKQ0K
KwkJcmV0dXJuIC1QVFJfRVJSKHNrYik7DQorDQorCXJlc3AgPSAoc3RydWN0IGhjaV9ycF9yZWFk
X2xvY2FsX3ZlcnNpb24gKilza2ItPmRhdGE7DQorCUJUX0lORk8oIiVzOiBydGw6IGV4YW1pbmlu
ZyBoY2lfdmVyPSUwMnggaGNpX3Jldj0lMDR4IGxtcF92ZXI9JTAyeCAiDQorCQkibG1wX3N1YnZl
cj0lMDR4IiwgaGRldi0+bmFtZSwgcmVzcC0+aGNpX3ZlciwgcmVzcC0+aGNpX3JldiwNCisJCXJl
c3AtPmxtcF92ZXIsIHJlc3AtPmxtcF9zdWJ2ZXIpOw0KKw0KKwlsbXBfc3VidmVyID0gbGUxNl90
b19jcHUocmVzcC0+bG1wX3N1YnZlcik7DQorCWtmcmVlX3NrYihza2IpOw0KKw0KKwkvKiBNYXRj
aCBhIHNldCBvZiBzdWJ2ZXIgdmFsdWVzIHRoYXQgY29ycmVzcG9uZCB0byBzdG9jayBmaXJtd2Fy
ZSwNCisJICogd2hpY2ggaXMgbm90IGNvbXBhdGlibGUgd2l0aCBzdGFuZGFyZCBidHVzYi4NCisJ
ICogSWYgbWF0Y2hlZCwgdXBsb2FkIGFuIGFsdGVybmF0aXZlIGZpcm13YXJlIHRoYXQgZG9lcyBj
b25mb3JtIHRvDQorCSAqIHN0YW5kYXJkIGJ0dXNiLiBPbmNlIHRoYXQgZmlybXdhcmUgaXMgdXBs
b2FkZWQsIHRoZSBzdWJ2ZXIgY2hhbmdlcw0KKwkgKiB0byBhIGRpZmZlcmVudCB2YWx1ZS4NCisJ
ICovDQorCXN3aXRjaCAobG1wX3N1YnZlcikgew0KKwljYXNlIFJUTF9ST01fTE1QXzg3MjNBOg0K
KwljYXNlIFJUTF9ST01fTE1QXzM0OTk6DQorCQlyZXR1cm4gYnR1c2Jfc2V0dXBfcnRsODcyM2Eo
aGRldik7DQorCWNhc2UgUlRMX1JPTV9MTVBfODcyM0I6DQorCQlyZXR1cm4gYnR1c2Jfc2V0dXBf
cnRsODcyM2IoaGRldiwgbG1wX3N1YnZlciwNCisJCQkJCSAgICAicnRsX2J0L3J0bDg3MjNiX2Z3
LmJpbiIpOw0KKwljYXNlIFJUTF9ST01fTE1QXzg4MjFBOg0KKwkJcmV0dXJuIGJ0dXNiX3NldHVw
X3J0bDg3MjNiKGhkZXYsIGxtcF9zdWJ2ZXIsDQorCQkJCQkgICAgInJ0bF9idC9ydGw4ODIxYV9m
dy5iaW4iKTsNCisJY2FzZSBSVExfUk9NX0xNUF84NzYxQToNCisJCXJldHVybiBidHVzYl9zZXR1
cF9ydGw4NzIzYihoZGV2LCBsbXBfc3VidmVyLA0KKwkJCQkJICAgICJydGxfYnQvcnRsODc2MWFf
ZncuYmluIik7DQorCWRlZmF1bHQ6DQorCQlCVF9JTkZPKCJydGw6IGFzc3VtaW5nIG5vIGZpcm13
YXJlIHVwbG9hZCBuZWVkZWQuIik7DQorCQlyZXR1cm4gMDsNCisJfQ0KK30NCisNCiBzdGF0aWMg
Y29uc3Qgc3RydWN0IGZpcm13YXJlICpidHVzYl9zZXR1cF9pbnRlbF9nZXRfZncoc3RydWN0IGhj
aV9kZXYgKmhkZXYsDQogCQkJCQkJICAgICAgIHN0cnVjdCBpbnRlbF92ZXJzaW9uICp2ZXIpICB7
IEBAIC0yNzc2LDYgKzMxNzIsOSBAQCBzdGF0aWMgaW50IGJ0dXNiX3Byb2JlKHN0cnVjdCB1c2Jf
aW50ZXJmYWNlICppbnRmLA0KIAkJaGRldi0+c2V0X2JkYWRkciA9IGJ0dXNiX3NldF9iZGFkZHJf
YXRoMzAxMjsNCiAJfQ0KIA0KKwlpZiAoaWQtPmRyaXZlcl9pbmZvICYgQlRVU0JfUkVBTFRFSykN
CisJCWhkZXYtPnNldHVwID0gYnR1c2Jfc2V0dXBfcmVhbHRlazsNCisNCiAJaWYgKGlkLT5kcml2
ZXJfaW5mbyAmIEJUVVNCX0FNUCkgew0KIAkJLyogQU1QIGNvbnRyb2xsZXJzIGRvIG5vdCBzdXBw
b3J0IFNDTyBwYWNrZXRzICovDQogCQlkYXRhLT5pc29jID0gTlVMTDsNCi0tDQoyLjEuMA0KDQo=

2015-04-16 21:16:43

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v8] Bluetooth: btusb: Add Realtek 8723A/8723B/8761A/8821A support

Hi Daniel,

> Realtek ship a variety of bluetooth USB devices that identify
> themselves with standard USB Bluetooth device class values, but
> require a special driver to actually work. Without that driver,
> you never get any scan results.
>
> More recently however, Realtek appear to have wisened up and simply
> posted a firmware update that makes these devices comply with
> normal btusb protocols. The firmware needs to be uploaded on each boot.
>
> Based on Realtek code from https://github.com/lwfinger/rtl8723au_bt
> ('new' branch).
>
> This enables bluetooth support in the Gigabyte Brix GB-BXBT-2807 which
> has this RTL8723BE USB device:
>
> T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=12 MxCh= 0
> D: Ver= 2.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
> P: Vendor=13d3 ProdID=3410 Rev= 2.00
> S: Manufacturer=Realtek
> S: Product=Bluetooth Radio
> S: SerialNumber=00e04c000001
> C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA
> I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
> E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
> E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
> I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
> E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
> I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
> E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
> I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
> E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
> I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
> E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
> I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
> E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
> I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
> E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
>
> There is no change to the USB descriptor after firmware update,
> however the version read by HCI_OP_READ_LOCAL_VERSION changes from
> 0x8723 to 0x3083.
>
> This has also been tested on RTL8723AE and RTL8821AE. Support for
> RTL8761A has also been added, but that is untested.
>
> Signed-off-by: Daniel Drake <[email protected]>
> Tested-by: Larry Finger <[email protected]>
> ---
> drivers/bluetooth/btusb.c | 399 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 399 insertions(+)

patch has been applied to bluetooth-next tree.

Regards

Marcel


2015-05-04 20:08:43

by Daniel Drake

[permalink] [raw]
Subject: Re: [PATCH v8] Bluetooth: btusb: Add Realtek 8723A/8723B/8761A/8821A support

On Mon, May 4, 2015 at 1:25 PM, Larry Finger <[email protected]> wrote:
> I am told that these changes have now landed in linux-next, and it is time
> to think about firmware. Are you sending it to linux-firmware, or should I
> do it?

I already sent that, no response so I'll do it again today. Thanks for
the reminder.

Daniel

2015-05-04 19:25:59

by Larry Finger

[permalink] [raw]
Subject: Re: [PATCH v8] Bluetooth: btusb: Add Realtek 8723A/8723B/8761A/8821A support

On 04/16/2015 03:09 PM, Daniel Drake wrote:
> Realtek ship a variety of bluetooth USB devices that identify
> themselves with standard USB Bluetooth device class values, but
> require a special driver to actually work. Without that driver,
> you never get any scan results.
>
> More recently however, Realtek appear to have wisened up and simply
> posted a firmware update that makes these devices comply with
> normal btusb protocols. The firmware needs to be uploaded on each boot.
>
> Based on Realtek code from https://github.com/lwfinger/rtl8723au_bt
> ('new' branch).

Daniel,

I am told that these changes have now landed in linux-next, and it is time to
think about firmware. Are you sending it to linux-firmware, or should I do it?

Thanks,

Larry