2012-09-22 01:59:51

by An, Tedd

[permalink] [raw]
Subject: [RFC 1/2] Bluetooth: Add driver extension for vendor specific init

From: Tedd Ho-Jeong An <[email protected]>

This patch provides an extension of btusb to support device vendor
can implement their own module to execute the vendor specific
device initialization before the stack sends generic BT device
initialization.

Signed-off-by: Tedd Ho-Jeong An <[email protected]>
---
drivers/bluetooth/btusb.c | 191 +++++++++++++++++++++++++-------------
drivers/bluetooth/btusb.h | 53 +++++++++++
include/net/bluetooth/hci_core.h | 10 ++
net/bluetooth/hci_core.c | 15 ++-
4 files changed, 204 insertions(+), 65 deletions(-)
create mode 100644 drivers/bluetooth/btusb.h

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index f637c25..afa1558 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -26,6 +26,7 @@

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+#include "btusb.h"

#define VERSION "0.6"

@@ -39,14 +40,59 @@ static bool reset = 1;

static struct usb_driver btusb_driver;

-#define BTUSB_IGNORE 0x01
-#define BTUSB_DIGIANSWER 0x02
-#define BTUSB_CSR 0x04
-#define BTUSB_SNIFFER 0x08
-#define BTUSB_BCM92035 0x10
-#define BTUSB_BROKEN_ISOC 0x20
-#define BTUSB_WRONG_SCO_MTU 0x40
-#define BTUSB_ATH3012 0x80
+/*
+ * Create btusb_driver_info struct for each driver_info flags used by
+ * blacklist since vendor's btusb driver will return btusb_driver_info struct.
+ */
+
+/*
+ * if the device is set to this, this menas that the device is generic and
+ * doesn't require any vendor specific handling
+ */
+static const struct btusb_driver_info generic = {
+ .description = "BTUSB Generic",
+ .flags = BTUSB_GENERIC,
+};
+
+static const struct btusb_driver_info ignore = {
+ .description = "BTUSB Ignore",
+ .flags = BTUSB_IGNORE,
+};
+
+static const struct btusb_driver_info digianswer = {
+ .description = "BTUSB DIGIANSWER",
+ .flags = BTUSB_DIGIANSWER,
+};
+
+static const struct btusb_driver_info csr = {
+ .description = "BTUSB CSR",
+ .flags = BTUSB_CSR,
+};
+
+static const struct btusb_driver_info sniffer = {
+ .description = "BTUSB Sniffer",
+ .flags = BTUSB_SNIFFER,
+};
+
+static const struct btusb_driver_info bcm92035 = {
+ .description = "BTUSB BCM92035",
+ .flags = BTUSB_BCM92035,
+};
+
+static const struct btusb_driver_info broken_isoc = {
+ .description = "BTUSB Broken ISOC",
+ .flags = BTUSB_BROKEN_ISOC,
+};
+
+static const struct btusb_driver_info wrong_sco_mtu = {
+ .description = "BTUSB Wrong SCO MTU",
+ .flags = BTUSB_WRONG_SCO_MTU,
+};
+
+static const struct btusb_driver_info ath3012 = {
+ .description = "BTUSB Ath3012",
+ .flags = BTUSB_ATH3012,
+};

static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -105,90 +151,89 @@ static struct usb_device_id btusb_table[] = {

{ } /* Terminating entry */
};
-
MODULE_DEVICE_TABLE(usb, btusb_table);

static struct usb_device_id blacklist_table[] = {
/* CSR BlueCore devices */
- { USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
+ { USB_DEVICE(0x0a12, 0x0001), .driver_info = (unsigned long) &csr },

/* Broadcom BCM2033 without firmware */
- { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0a5c, 0x2033), .driver_info = (unsigned long) &ignore },

/* Atheros 3011 with sflash firmware */
- { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
- { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
- { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
- { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
- { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0cf3, 0x3002), .driver_info = (unsigned long) &ignore },
+ { USB_DEVICE(0x0cf3, 0xe019), .driver_info = (unsigned long) &ignore },
+ { USB_DEVICE(0x13d3, 0x3304), .driver_info = (unsigned long) &ignore },
+ { USB_DEVICE(0x0930, 0x0215), .driver_info = (unsigned long) &ignore },
+ { USB_DEVICE(0x0489, 0xe03d), .driver_info = (unsigned long) &ignore },

/* Atheros AR9285 Malbec with sflash firmware */
- { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x03f0, 0x311d), .driver_info = (unsigned long) &ignore },

/* Atheros 3012 with sflash firmware */
- { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x3004), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x0cf3, 0x311d), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x13d3, 0x3362), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x0cf3, 0xe004), .driver_info = (unsigned long) &ath3012 },
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = (unsigned long) &ath3012 },

/* Atheros AR5BBU12 with sflash firmware */
- { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0489, 0xe02c), .driver_info = (unsigned long) &ignore },

/* Atheros AR5BBU12 with sflash firmware */
- { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe03c), .driver_info = (unsigned long) &ath3012 },

/* Broadcom BCM2035 */
- { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
+ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x0a5c, 0x200a), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x0a5c, 0x2009), .driver_info = (unsigned long) &bcm92035 },

/* Broadcom BCM2045 */
- { USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x2039), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x0a5c, 0x2101), .driver_info = (unsigned long) &wrong_sco_mtu },

/* IBM/Lenovo ThinkPad with Broadcom chip */
- { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0a5c, 0x201e), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x0a5c, 0x2110), .driver_info = (unsigned long) &wrong_sco_mtu },

/* HP laptop with Broadcom chip */
- { USB_DEVICE(0x03f0, 0x171d), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x03f0, 0x171d), .driver_info = (unsigned long) &wrong_sco_mtu },

/* Dell laptop with Broadcom chip */
- { USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x413c, 0x8126), .driver_info = (unsigned long) &wrong_sco_mtu },

/* Dell Wireless 370 and 410 devices */
- { USB_DEVICE(0x413c, 0x8152), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x413c, 0x8152), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x413c, 0x8156), .driver_info = (unsigned long) &wrong_sco_mtu },

/* Belkin F8T012 and F8T013 devices */
- { USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_WRONG_SCO_MTU },
- { USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x050d, 0x0012), .driver_info = (unsigned long) &wrong_sco_mtu },
+ { USB_DEVICE(0x050d, 0x0013), .driver_info = (unsigned long) &wrong_sco_mtu },

/* Asus WL-BTD202 device */
- { USB_DEVICE(0x0b05, 0x1715), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x0b05, 0x1715), .driver_info = (unsigned long) &wrong_sco_mtu },

/* Kensington Bluetooth USB adapter */
- { USB_DEVICE(0x047d, 0x105e), .driver_info = BTUSB_WRONG_SCO_MTU },
+ { USB_DEVICE(0x047d, 0x105e), .driver_info = (unsigned long) &wrong_sco_mtu },

/* RTX Telecom based adapters with buggy SCO support */
- { USB_DEVICE(0x0400, 0x0807), .driver_info = BTUSB_BROKEN_ISOC },
- { USB_DEVICE(0x0400, 0x080a), .driver_info = BTUSB_BROKEN_ISOC },
+ { USB_DEVICE(0x0400, 0x0807), .driver_info = (unsigned long) &broken_isoc },
+ { USB_DEVICE(0x0400, 0x080a), .driver_info = (unsigned long) &broken_isoc },

/* CONWISE Technology based adapters with buggy SCO support */
- { USB_DEVICE(0x0e5e, 0x6622), .driver_info = BTUSB_BROKEN_ISOC },
+ { USB_DEVICE(0x0e5e, 0x6622), .driver_info = (unsigned long) &broken_isoc },

/* Digianswer devices */
- { USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
- { USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x08fd, 0x0001), .driver_info = (unsigned long) &digianswer },
+ { USB_DEVICE(0x08fd, 0x0002), .driver_info = (unsigned long) &ignore },

/* CSR BlueCore Bluetooth Sniffer */
- { USB_DEVICE(0x0a12, 0x0002), .driver_info = BTUSB_SNIFFER },
+ { USB_DEVICE(0x0a12, 0x0002), .driver_info = (unsigned long) &sniffer },

/* Frontline ComProbe Bluetooth Sniffer */
- { USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER },
+ { USB_DEVICE(0x16d3, 0x0002), .driver_info = (unsigned long) &sniffer },

{ } /* Terminating entry */
};
@@ -910,12 +955,12 @@ static void btusb_waker(struct work_struct *work)
usb_autopm_put_interface(data->intf);
}

-static int btusb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_endpoint_descriptor *ep_desc;
struct btusb_data *data;
struct hci_dev *hdev;
+ struct btusb_driver_info *info;
int i, err;

BT_DBG("intf %p id %p", intf, id);
@@ -931,19 +976,28 @@ static int btusb_probe(struct usb_interface *intf,
id = match;
}

- if (id->driver_info == BTUSB_IGNORE)
+ /*
+ * Make sure the driver_info is not null or 0 because the code below
+ * need to access the flags
+ */
+ if (!id->driver_info)
+ info = (struct btusb_driver_info *) &generic;
+ else
+ info = (struct btusb_driver_info *) id->driver_info;
+
+ if (info->flags == BTUSB_IGNORE)
return -ENODEV;

- if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
+ if (ignore_dga && (info->flags & BTUSB_DIGIANSWER))
return -ENODEV;

- if (ignore_csr && id->driver_info & BTUSB_CSR)
+ if (ignore_csr && (info->flags & BTUSB_CSR))
return -ENODEV;

- if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
+ if (ignore_sniffer && (info->flags & BTUSB_SNIFFER))
return -ENODEV;

- if (id->driver_info & BTUSB_ATH3012) {
+ if (info->flags & BTUSB_ATH3012) {
struct usb_device *udev = interface_to_usbdev(intf);

/* Old firmware would otherwise let ath3k driver load
@@ -1012,26 +1066,30 @@ static int btusb_probe(struct usb_interface *intf,
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;

+ /* vendor specific device initialization routines */
+ hdev->vsdev_init = info->vsdev_init;
+ hdev->vsdev_event = info->vsdev_event;
+
/* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1);

if (!reset)
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);

- if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
+ if (force_scofix || (info->flags & BTUSB_WRONG_SCO_MTU)) {
if (!disable_scofix)
set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
}

- if (id->driver_info & BTUSB_BROKEN_ISOC)
+ if (info->flags & BTUSB_BROKEN_ISOC)
data->isoc = NULL;

- if (id->driver_info & BTUSB_DIGIANSWER) {
+ if (info->flags & BTUSB_DIGIANSWER) {
data->cmdreq_type = USB_TYPE_VENDOR;
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
}

- if (id->driver_info & BTUSB_CSR) {
+ if (info->flags & BTUSB_CSR) {
struct usb_device *udev = data->udev;

/* Old firmware would otherwise execute USB reset */
@@ -1039,7 +1097,7 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
}

- if (id->driver_info & BTUSB_SNIFFER) {
+ if (info->flags & BTUSB_SNIFFER) {
struct usb_device *udev = data->udev;

/* New sniffer firmware has crippled HCI interface */
@@ -1049,7 +1107,7 @@ static int btusb_probe(struct usb_interface *intf,
data->isoc = NULL;
}

- if (id->driver_info & BTUSB_BCM92035) {
+ if (info->flags & BTUSB_BCM92035) {
unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
struct sk_buff *skb;

@@ -1079,8 +1137,9 @@ static int btusb_probe(struct usb_interface *intf,

return 0;
}
+EXPORT_SYMBOL_GPL(btusb_probe);

-static void btusb_disconnect(struct usb_interface *intf)
+void btusb_disconnect(struct usb_interface *intf)
{
struct btusb_data *data = usb_get_intfdata(intf);
struct hci_dev *hdev;
@@ -1105,9 +1164,10 @@ static void btusb_disconnect(struct usb_interface *intf)

hci_free_dev(hdev);
}
+EXPORT_SYMBOL_GPL(btusb_disconnect);

#ifdef CONFIG_PM
-static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
+int btusb_suspend(struct usb_interface *intf, pm_message_t message)
{
struct btusb_data *data = usb_get_intfdata(intf);

@@ -1133,6 +1193,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)

return 0;
}
+EXPORT_SYMBOL_GPL(btusb_suspend);

static void play_deferred(struct btusb_data *data)
{
@@ -1149,7 +1210,7 @@ static void play_deferred(struct btusb_data *data)
usb_scuttle_anchored_urbs(&data->deferred);
}

-static int btusb_resume(struct usb_interface *intf)
+int btusb_resume(struct usb_interface *intf)
{
struct btusb_data *data = usb_get_intfdata(intf);
struct hci_dev *hdev = data->hdev;
@@ -1205,8 +1266,10 @@ done:

return err;
}
+EXPORT_SYMBOL_GPL(btusb_resume);
#endif

+
static struct usb_driver btusb_driver = {
.name = "btusb",
.probe = btusb_probe,
diff --git a/drivers/bluetooth/btusb.h b/drivers/bluetooth/btusb.h
new file mode 100644
index 0000000..c26a845
--- /dev/null
+++ b/drivers/bluetooth/btusb.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * Generic Bluetooth USB driver
+ *
+ * Copyright (C) 2005-2008 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef _BTUSB_H
+#define _BTUSB_H
+
+struct btusb_driver_info {
+ char *description;
+ int flags;
+#define BTUSB_GENERIC 0x00
+#define BTUSB_IGNORE 0x01
+#define BTUSB_DIGIANSWER 0x02
+#define BTUSB_CSR 0x04
+#define BTUSB_SNIFFER 0x08
+#define BTUSB_BCM92035 0x10
+#define BTUSB_BROKEN_ISOC 0x20
+#define BTUSB_WRONG_SCO_MTU 0x40
+#define BTUSB_ATH3012 0x80
+
+ /* entry point for vendor specific device initialization */
+ int (*vsdev_init)(struct hci_dev *hdev);
+
+ /* event handler during vendor specific device initiation phase */
+ void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);
+};
+
+extern int btusb_probe(struct usb_interface *, const struct usb_device_id *);
+extern void btusb_disconnect(struct usb_interface *);
+#ifdef CONFIG_PM
+extern int btusb_suspend(struct usb_interface *, pm_message_t);
+extern int btusb_resume(struct usb_interface *);
+#endif
+
+#endif /* _BTUSB_H */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6a3337e..4af601d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -275,6 +275,16 @@ struct hci_dev {
int (*send)(struct sk_buff *skb);
void (*notify)(struct hci_dev *hdev, unsigned int evt);
int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
+
+ /*
+ * TODO: Added following members for vendor specific initialization to
+ * make the bluetooth.ko transparent to the interface.
+ * These members are set by the vendor provided driver
+ */
+ int vsdev_init_done;
+ void *vsdev_priv_data;
+ int (*vsdev_init)(struct hci_dev *hdev);
+ void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);
};

struct hci_conn {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e407051..80aa13f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -685,6 +685,15 @@ int hci_dev_open(__u16 dev)
set_bit(HCI_INIT, &hdev->flags);
hdev->init_last_cmd = 0;

+ /* vendor specific device initialization */
+ if (hdev->vsdev_init) {
+ ret = hdev->vsdev_init(hdev);
+ hdev->vsdev_init_done = 1;
+ hdev->vsdev_event = NULL;
+ if (ret < 0)
+ goto done;
+ }
+
ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);

if (lmp_host_le_capable(hdev))
@@ -2119,6 +2128,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)

return 0;
}
+EXPORT_SYMBOL(hci_send_cmd);

/* Get data from the previously sent command */
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
@@ -2800,7 +2810,10 @@ static void hci_rx_work(struct work_struct *work)
switch (bt_cb(skb)->pkt_type) {
case HCI_EVENT_PKT:
BT_DBG("%s Event packet", hdev->name);
- hci_event_packet(hdev, skb);
+ if (hdev->vsdev_event && !hdev->vsdev_init_done)
+ hdev->vsdev_event(hdev, skb);
+ else
+ hci_event_packet(hdev, skb);
break;

case HCI_ACLDATA_PKT:
--
1.7.9.5


2012-10-25 06:38:52

by Ho, Albert O

[permalink] [raw]
Subject: RE: [RFC 1/2] Bluetooth: Add driver extension for vendor specific init

QWNrbm93bGVkZ2VkLg0KDQpSZWdhcmRzLA0KQWxiZXJ0DQoNCg0KLS0tLS1PcmlnaW5hbCBNZXNz
YWdlLS0tLS0NCkZyb206IE1hcmNlbCBIb2x0bWFubiBbbWFpbHRvOm1hcmNlbEBob2x0bWFubi5v
cmddIA0KU2VudDogV2VkbmVzZGF5LCBPY3RvYmVyIDI0LCAyMDEyIDg6MTggQU0NClRvOiBIbywg
QWxiZXJ0IE8NCkNjOiBsaW51eC1ibHVldG9vdGg7IEhlZGJlcmcsIEpvaGFuOyB0ZWRkLmhqLmFu
QGdtYWlsLmNvbTsgQW4sIFRlZGQNClN1YmplY3Q6IFJlOiBbUkZDIDEvMl0gQmx1ZXRvb3RoOiBB
ZGQgZHJpdmVyIGV4dGVuc2lvbiBmb3IgdmVuZG9yIHNwZWNpZmljIGluaXQNCg0KSGkgQWxiZXJ0
LA0KDQo+ID4gVGhpcyBwYXRjaCBwcm92aWRlcyBhbiBleHRlbnNpb24gb2YgYnR1c2IgdG8gc3Vw
cG9ydCBkZXZpY2UgdmVuZG9yIA0KPiA+IGNhbiBpbXBsZW1lbnQgdGhlaXIgb3duIG1vZHVsZSB0
byBleGVjdXRlIHRoZSB2ZW5kb3Igc3BlY2lmaWMgZGV2aWNlIA0KPiA+IGluaXRpYWxpemF0aW9u
IGJlZm9yZSB0aGUgc3RhY2sgc2VuZHMgZ2VuZXJpYyBCVCBkZXZpY2UgDQo+ID4gaW5pdGlhbGl6
YXRpb24uDQo+ID4gDQo+ID4gU2lnbmVkLW9mZi1ieTogVGVkZCBIby1KZW9uZyBBbiA8dGVkZC5h
bkBpbnRlbC5jb20+DQo+ID4gLS0tDQo+ID4gIGRyaXZlcnMvYmx1ZXRvb3RoL2J0dXNiLmMgICAg
ICAgIHwgIDE5MSArKysrKysrKysrKysrKysrKysrKysrKysrLS0tLS0tLS0tLS0tLQ0KPiA+ICBk
cml2ZXJzL2JsdWV0b290aC9idHVzYi5oICAgICAgICB8ICAgNTMgKysrKysrKysrKysNCj4gPiAg
aW5jbHVkZS9uZXQvYmx1ZXRvb3RoL2hjaV9jb3JlLmggfCAgIDEwICsrDQo+ID4gIG5ldC9ibHVl
dG9vdGgvaGNpX2NvcmUuYyAgICAgICAgIHwgICAxNSArKy0NCj4gPiAgNCBmaWxlcyBjaGFuZ2Vk
LCAyMDQgaW5zZXJ0aW9ucygrKSwgNjUgZGVsZXRpb25zKC0pICBjcmVhdGUgbW9kZQ0KPiA+IDEw
MDY0NCBkcml2ZXJzL2JsdWV0b290aC9idHVzYi5oDQo+ID4gDQo+ID4gZGlmZiAtLWdpdCBhL2Ry
aXZlcnMvYmx1ZXRvb3RoL2J0dXNiLmMgYi9kcml2ZXJzL2JsdWV0b290aC9idHVzYi5jIA0KPiA+
IGluZGV4IGY2MzdjMjUuLmFmYTE1NTggMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9ibHVldG9v
dGgvYnR1c2IuYw0KPiA+ICsrKyBiL2RyaXZlcnMvYmx1ZXRvb3RoL2J0dXNiLmMNCj4gPiBAQCAt
MjYsNiArMjYsNyBAQA0KPiA+ICANCj4gPiAgI2luY2x1ZGUgPG5ldC9ibHVldG9vdGgvYmx1ZXRv
b3RoLmg+ICAjaW5jbHVkZSANCj4gPiA8bmV0L2JsdWV0b290aC9oY2lfY29yZS5oPg0KPiA+ICsj
aW5jbHVkZSAiYnR1c2IuaCINCj4gPiAgDQo+ID4gICNkZWZpbmUgVkVSU0lPTiAiMC42Ig0KPiA+
ICANCj4gPiBAQCAtMzksMTQgKzQwLDU5IEBAIHN0YXRpYyBib29sIHJlc2V0ID0gMTsNCj4gPiAg
DQo+ID4gIHN0YXRpYyBzdHJ1Y3QgdXNiX2RyaXZlciBidHVzYl9kcml2ZXI7DQo+ID4gIA0KPiA+
IC0jZGVmaW5lIEJUVVNCX0lHTk9SRQkJMHgwMQ0KPiA+IC0jZGVmaW5lIEJUVVNCX0RJR0lBTlNX
RVIJMHgwMg0KPiA+IC0jZGVmaW5lIEJUVVNCX0NTUgkJMHgwNA0KPiA+IC0jZGVmaW5lIEJUVVNC
X1NOSUZGRVIJCTB4MDgNCj4gPiAtI2RlZmluZSBCVFVTQl9CQ005MjAzNQkJMHgxMA0KPiA+IC0j
ZGVmaW5lIEJUVVNCX0JST0tFTl9JU09DCTB4MjANCj4gPiAtI2RlZmluZSBCVFVTQl9XUk9OR19T
Q09fTVRVCTB4NDANCj4gPiAtI2RlZmluZSBCVFVTQl9BVEgzMDEyCQkweDgwDQo+ID4gKy8qDQo+
ID4gKyAqIENyZWF0ZSBidHVzYl9kcml2ZXJfaW5mbyBzdHJ1Y3QgZm9yIGVhY2ggZHJpdmVyX2lu
Zm8gZmxhZ3MgdXNlZCANCj4gPiArYnkNCj4gPiArICogYmxhY2tsaXN0IHNpbmNlIHZlbmRvcidz
IGJ0dXNiIGRyaXZlciB3aWxsIHJldHVybiBidHVzYl9kcml2ZXJfaW5mbyBzdHJ1Y3QuDQo+ID4g
KyAqLw0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogaWYgdGhlIGRldmljZSBpcyBzZXQgdG8gdGhp
cywgdGhpcyBtZW5hcyB0aGF0IHRoZSBkZXZpY2UgaXMgDQo+ID4gK2dlbmVyaWMgYW5kDQo+ID4g
KyAqIGRvZXNuJ3QgcmVxdWlyZSBhbnkgdmVuZG9yIHNwZWNpZmljIGhhbmRsaW5nICAqLyBzdGF0
aWMgY29uc3QgDQo+ID4gK3N0cnVjdCBidHVzYl9kcml2ZXJfaW5mbyBnZW5lcmljID0gew0KPiA+
ICsJLmRlc2NyaXB0aW9uCT0gIkJUVVNCIEdlbmVyaWMiLA0KPiA+ICsJLmZsYWdzCQk9IEJUVVNC
X0dFTkVSSUMsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGJ0dXNi
X2RyaXZlcl9pbmZvIGlnbm9yZSA9IHsNCj4gPiArCS5kZXNjcmlwdGlvbgk9ICJCVFVTQiBJZ25v
cmUiLA0KPiA+ICsJLmZsYWdzCQk9IEJUVVNCX0lHTk9SRSwNCj4gPiArfTsNCj4gDQo+ID4+IEkg
bGlrZSB0aGUgZWZmb3J0LCBidXQgSSB0aGluayB5b3Ugd2VudCBhIGxpdHRsZSBiaXQgdG9vIGZh
ciBoZXJlLiBGb3IgdGhlc2Ugc2ltcGxlIG9uZXMsIHdlIGNhbiBlYXNpbHkga2VlcCBvdXIgc2lt
cGxlIGJsYWNrbGlzdC4gSXQga2VlcHMgdGhlIGNvZGUgbW9yZSByZWFkYWJsZSB0aGFuIHRoaXMg
cGFydC4gQnV0IEkgZG8gYXBwcmVjaWF0ZSB0aGUgYXR0ZW1wdCBpbiB1bmlmeWluZyB0aGlzLg0K
PiANCj4gDQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGJ0dXNiX2RyaXZlcl9pbmZv
IGRpZ2lhbnN3ZXIgPSB7DQo+ID4gKwkuZGVzY3JpcHRpb24JPSAiQlRVU0IgRElHSUFOU1dFUiIs
DQo+ID4gKwkuZmxhZ3MJCT0gQlRVU0JfRElHSUFOU1dFUiwNCj4gPiArfTsNCj4gPiArDQo+ID4g
K3N0YXRpYyBjb25zdCBzdHJ1Y3QgYnR1c2JfZHJpdmVyX2luZm8gY3NyID0gew0KPiA+ICsJLmRl
c2NyaXB0aW9uCT0gIkJUVVNCIENTUiIsDQo+ID4gKwkuZmxhZ3MJCT0gQlRVU0JfQ1NSLA0KPiA+
ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBidHVzYl9kcml2ZXJfaW5mbyBz
bmlmZmVyID0gew0KPiA+ICsJLmRlc2NyaXB0aW9uCT0gIkJUVVNCIFNuaWZmZXIiLA0KPiA+ICsJ
LmZsYWdzCQk9IEJUVVNCX1NOSUZGRVIsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29u
c3Qgc3RydWN0IGJ0dXNiX2RyaXZlcl9pbmZvIGJjbTkyMDM1ID0gew0KPiA+ICsJLmRlc2NyaXB0
aW9uCT0gIkJUVVNCIEJDTTkyMDM1IiwNCj4gPiArCS5mbGFncwkJPSBCVFVTQl9CQ005MjAzNSwN
Cj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgYnR1c2JfZHJpdmVyX2lu
Zm8gYnJva2VuX2lzb2MgPSB7DQo+ID4gKwkuZGVzY3JpcHRpb24JPSAiQlRVU0IgQnJva2VuIElT
T0MiLA0KPiA+ICsJLmZsYWdzCQk9IEJUVVNCX0JST0tFTl9JU09DLA0KPiA+ICt9Ow0KPiA+ICsN
Cj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBidHVzYl9kcml2ZXJfaW5mbyB3cm9uZ19zY29fbXR1
ID0gew0KPiA+ICsJLmRlc2NyaXB0aW9uCT0gIkJUVVNCIFdyb25nIFNDTyBNVFUiLA0KPiA+ICsJ
LmZsYWdzCQk9IEJUVVNCX1dST05HX1NDT19NVFUsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0
aWMgY29uc3Qgc3RydWN0IGJ0dXNiX2RyaXZlcl9pbmZvIGF0aDMwMTIgPSB7DQo+ID4gKwkuZGVz
Y3JpcHRpb24JPSAiQlRVU0IgQXRoMzAxMiIsDQo+ID4gKwkuZmxhZ3MJCT0gQlRVU0JfQVRIMzAx
MiwNCj4gPiArfTsNCj4gPiAgDQo+ID4gIHN0YXRpYyBzdHJ1Y3QgdXNiX2RldmljZV9pZCBidHVz
Yl90YWJsZVtdID0gew0KPiA+ICAJLyogR2VuZXJpYyBCbHVldG9vdGggVVNCIGRldmljZSAqLyBA
QCAtMTA1LDkwICsxNTEsODkgQEAgc3RhdGljIA0KPiA+IHN0cnVjdCB1c2JfZGV2aWNlX2lkIGJ0
dXNiX3RhYmxlW10gPSB7DQo+ID4gIA0KPiA+ICAJeyB9CS8qIFRlcm1pbmF0aW5nIGVudHJ5ICov
DQo+ID4gIH07DQo+ID4gLQ0KPiA+ICBNT0RVTEVfREVWSUNFX1RBQkxFKHVzYiwgYnR1c2JfdGFi
bGUpOw0KPiA+ICANCj4gPiAgc3RhdGljIHN0cnVjdCB1c2JfZGV2aWNlX2lkIGJsYWNrbGlzdF90
YWJsZVtdID0gew0KPiA+ICAJLyogQ1NSIEJsdWVDb3JlIGRldmljZXMgKi8NCj4gPiAtCXsgVVNC
X0RFVklDRSgweDBhMTIsIDB4MDAwMSksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX0NTUiB9LA0KPiA+
ICsJeyBVU0JfREVWSUNFKDB4MGExMiwgMHgwMDAxKSwgLmRyaXZlcl9pbmZvID0gKHVuc2lnbmVk
IGxvbmcpICZjc3IgDQo+ID4gK30sDQo+IA0KPiA+PiBLZWVwIHRoZSBibGFja2xpc3RfdGFibGUg
YXMgaXQgaXMuIFRoZSBpbXBvcnRhbnQgdGFibGUgdG8gbW9kaWZ5IGlzIGJ0dXNiX3RhYmxlIGFu
ZCB1c2UgYSBjb21tb24gZHJpdmVyX2luZm8gdGhhdCB3aWxsIGJlIHNoYXJlZCBiZXR3ZWVuIGRy
aXZlcnMuDQo+IA0KPiA+PiBUaGF0IHdvdWxkIGFsc28gbWFrZSBpdCBzaW1wbGUgdG8ganVzdCBh
ZGQgQlRVU0JfSUdOT1JFIG9yIGEgbmV3IEJUVVNCX1ZFTkRPUiBmbGFnIHRvIGNhbGwgb3V0IHRo
ZSBkcml2ZXJzIHRoYXQgaGF2ZSBhIHNlcGFyYXRlIGRyaXZlciB3aXRoIGEgdmVuZG9yIGluaXQg
ZnVuY3Rpb24sIGJ1dCB3b3VsZCBtYXRjaCA+PiB0aGUgQmx1ZXRvb3RoIGdlbmVyYWwgVVNCIGRl
c2NyaXB0b3JzLg0KPiANCj4gSSBsb29rZWQgYXQgdXNibmV0IG1pbmlkcml2ZXIgYXMgeW91IHN1
Z2dlc3RlZC4gIElmIHdlIGRvIGEgc2ltaWxhciBzY2hlbWUgc3VjaCB0aGF0IGJ0dXNiX3Byb2Jl
KCkgaW52b2tlcyB0aGUgbWluaV9kcml2ZXIncyBiaW5kKCkvdW5iaW5kKCkgdGhlbiBidHVzYidz
IHVzYWdlIG9mIGRyaXZlcl9pbmZvIHdpbGwgbmVlZCB0byBjaGFuZ2UgZnJvbSBzdG9yaW5nIGZs
YWdzIChleDogQlRVU0JfSUdOT1JFKSBhbmQgY2hhbmdlIHRvIHN0b3JlICJzdGF0aWMgY29uc3Qg
c3RydWN0IiB3aGVyZSBpdCBob2xkcyBhIHN0cnVjdCBjb250YWluaW5nIHRoZSBtaW5pLWRyaXZl
cidzIGJpbmQvdW5iaW5kIGZ1bmN0aW9ucyAoanVzdCBsaWtlIHVzYm5ldCBtaW5pZHJpdmVyKS4g
ICBBcmUgeW91IGdvb2Qgd2l0aCB0aGlzIGNoYW5nZT8gIEkgYWxzbyB3YW50IHRvIG1lbnRpb24g
dGhhdCBpbiB0aGUgcGF0Y2ggY29udGFpbmluZyB0aGUgQlQgVVNCIG1pbmkgZHJpdmVyIHRlbXBs
YXRlLCBpdCBhbHJlYWR5IGhhcyBpdHMgb3duIG1vZHVsZV91c2JfZHJpdmVyKCkgc2VjdGlvbiB3
aXRoIGl0cyBWSUQvUElEIGxpc3RlZC4NCg0KeW91IGtub3cgd2hhdC4gSnVzdCBzZW5kIGFyb3Vu
ZCB3aGF0IHlvdSBoYXZlIHJpZ2h0IG5vdyBhZnRlciB0aGUgY2xlYW51cCBhbmQgdGhlbiBJIGNh
biB0YWtlIGFub3RoZXIgbG9vayBhdCBpdC4NCg0KUmVnYXJkcw0KDQpNYXJjZWwNCg0KDQo=

2012-10-24 15:18:19

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC 1/2] Bluetooth: Add driver extension for vendor specific init

Hi Albert,

> > This patch provides an extension of btusb to support device vendor can
> > implement their own module to execute the vendor specific device
> > initialization before the stack sends generic BT device
> > initialization.
> >
> > Signed-off-by: Tedd Ho-Jeong An <[email protected]>
> > ---
> > drivers/bluetooth/btusb.c | 191 +++++++++++++++++++++++++-------------
> > drivers/bluetooth/btusb.h | 53 +++++++++++
> > include/net/bluetooth/hci_core.h | 10 ++
> > net/bluetooth/hci_core.c | 15 ++-
> > 4 files changed, 204 insertions(+), 65 deletions(-) create mode
> > 100644 drivers/bluetooth/btusb.h
> >
> > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> > index f637c25..afa1558 100644
> > --- a/drivers/bluetooth/btusb.c
> > +++ b/drivers/bluetooth/btusb.c
> > @@ -26,6 +26,7 @@
> >
> > #include <net/bluetooth/bluetooth.h>
> > #include <net/bluetooth/hci_core.h>
> > +#include "btusb.h"
> >
> > #define VERSION "0.6"
> >
> > @@ -39,14 +40,59 @@ static bool reset = 1;
> >
> > static struct usb_driver btusb_driver;
> >
> > -#define BTUSB_IGNORE 0x01
> > -#define BTUSB_DIGIANSWER 0x02
> > -#define BTUSB_CSR 0x04
> > -#define BTUSB_SNIFFER 0x08
> > -#define BTUSB_BCM92035 0x10
> > -#define BTUSB_BROKEN_ISOC 0x20
> > -#define BTUSB_WRONG_SCO_MTU 0x40
> > -#define BTUSB_ATH3012 0x80
> > +/*
> > + * Create btusb_driver_info struct for each driver_info flags used by
> > + * blacklist since vendor's btusb driver will return btusb_driver_info struct.
> > + */
> > +
> > +/*
> > + * if the device is set to this, this menas that the device is
> > +generic and
> > + * doesn't require any vendor specific handling */ static const
> > +struct btusb_driver_info generic = {
> > + .description = "BTUSB Generic",
> > + .flags = BTUSB_GENERIC,
> > +};
> > +
> > +static const struct btusb_driver_info ignore = {
> > + .description = "BTUSB Ignore",
> > + .flags = BTUSB_IGNORE,
> > +};
>
> >> I like the effort, but I think you went a little bit too far here. For these simple ones, we can easily keep our simple blacklist. It keeps the code more readable than this part. But I do appreciate the attempt in unifying this.
>
>
> > +
> > +static const struct btusb_driver_info digianswer = {
> > + .description = "BTUSB DIGIANSWER",
> > + .flags = BTUSB_DIGIANSWER,
> > +};
> > +
> > +static const struct btusb_driver_info csr = {
> > + .description = "BTUSB CSR",
> > + .flags = BTUSB_CSR,
> > +};
> > +
> > +static const struct btusb_driver_info sniffer = {
> > + .description = "BTUSB Sniffer",
> > + .flags = BTUSB_SNIFFER,
> > +};
> > +
> > +static const struct btusb_driver_info bcm92035 = {
> > + .description = "BTUSB BCM92035",
> > + .flags = BTUSB_BCM92035,
> > +};
> > +
> > +static const struct btusb_driver_info broken_isoc = {
> > + .description = "BTUSB Broken ISOC",
> > + .flags = BTUSB_BROKEN_ISOC,
> > +};
> > +
> > +static const struct btusb_driver_info wrong_sco_mtu = {
> > + .description = "BTUSB Wrong SCO MTU",
> > + .flags = BTUSB_WRONG_SCO_MTU,
> > +};
> > +
> > +static const struct btusb_driver_info ath3012 = {
> > + .description = "BTUSB Ath3012",
> > + .flags = BTUSB_ATH3012,
> > +};
> >
> > static struct usb_device_id btusb_table[] = {
> > /* Generic Bluetooth USB device */
> > @@ -105,90 +151,89 @@ static struct usb_device_id btusb_table[] = {
> >
> > { } /* Terminating entry */
> > };
> > -
> > MODULE_DEVICE_TABLE(usb, btusb_table);
> >
> > static struct usb_device_id blacklist_table[] = {
> > /* CSR BlueCore devices */
> > - { USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
> > + { USB_DEVICE(0x0a12, 0x0001), .driver_info = (unsigned long) &csr },
>
> >> Keep the blacklist_table as it is. The important table to modify is btusb_table and use a common driver_info that will be shared between drivers.
>
> >> That would also make it simple to just add BTUSB_IGNORE or a new BTUSB_VENDOR flag to call out the drivers that have a separate driver with a vendor init function, but would match >> the Bluetooth general USB descriptors.
>
> I looked at usbnet minidriver as you suggested. If we do a similar scheme such that btusb_probe() invokes the mini_driver's bind()/unbind() then btusb's usage of driver_info will need to change from storing flags (ex: BTUSB_IGNORE) and change to store "static const struct" where it holds a struct containing the mini-driver's bind/unbind functions (just like usbnet minidriver). Are you good with this change? I also want to mention that in the patch containing the BT USB mini driver template, it already has its own module_usb_driver() section with its VID/PID listed.

you know what. Just send around what you have right now after the
cleanup and then I can take another look at it.

Regards

Marcel



2012-10-24 08:27:54

by Ho, Albert O

[permalink] [raw]
Subject: RE: [RFC 1/2] Bluetooth: Add driver extension for vendor specific init

SGkgTWFyY2VsLA0KDQpJIGhhdmUgYSBxdWVzdGlvbiBhZnRlciBvdXIgY2hhdCB2aWEgSVJDLiAg
U2VlIGJlbG93Lg0KIA0KDQo+IFRoaXMgcGF0Y2ggcHJvdmlkZXMgYW4gZXh0ZW5zaW9uIG9mIGJ0
dXNiIHRvIHN1cHBvcnQgZGV2aWNlIHZlbmRvciBjYW4gDQo+IGltcGxlbWVudCB0aGVpciBvd24g
bW9kdWxlIHRvIGV4ZWN1dGUgdGhlIHZlbmRvciBzcGVjaWZpYyBkZXZpY2UgDQo+IGluaXRpYWxp
emF0aW9uIGJlZm9yZSB0aGUgc3RhY2sgc2VuZHMgZ2VuZXJpYyBCVCBkZXZpY2UgDQo+IGluaXRp
YWxpemF0aW9uLg0KPiANCj4gU2lnbmVkLW9mZi1ieTogVGVkZCBIby1KZW9uZyBBbiA8dGVkZC5h
bkBpbnRlbC5jb20+DQo+IC0tLQ0KPiAgZHJpdmVycy9ibHVldG9vdGgvYnR1c2IuYyAgICAgICAg
fCAgMTkxICsrKysrKysrKysrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tDQo+ICBkcml2ZXJz
L2JsdWV0b290aC9idHVzYi5oICAgICAgICB8ICAgNTMgKysrKysrKysrKysNCj4gIGluY2x1ZGUv
bmV0L2JsdWV0b290aC9oY2lfY29yZS5oIHwgICAxMCArKw0KPiAgbmV0L2JsdWV0b290aC9oY2lf
Y29yZS5jICAgICAgICAgfCAgIDE1ICsrLQ0KPiAgNCBmaWxlcyBjaGFuZ2VkLCAyMDQgaW5zZXJ0
aW9ucygrKSwgNjUgZGVsZXRpb25zKC0pICBjcmVhdGUgbW9kZSANCj4gMTAwNjQ0IGRyaXZlcnMv
Ymx1ZXRvb3RoL2J0dXNiLmgNCj4gDQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2JsdWV0b290aC9i
dHVzYi5jIGIvZHJpdmVycy9ibHVldG9vdGgvYnR1c2IuYyANCj4gaW5kZXggZjYzN2MyNS4uYWZh
MTU1OCAxMDA2NDQNCj4gLS0tIGEvZHJpdmVycy9ibHVldG9vdGgvYnR1c2IuYw0KPiArKysgYi9k
cml2ZXJzL2JsdWV0b290aC9idHVzYi5jDQo+IEBAIC0yNiw2ICsyNiw3IEBADQo+ICANCj4gICNp
bmNsdWRlIDxuZXQvYmx1ZXRvb3RoL2JsdWV0b290aC5oPg0KPiAgI2luY2x1ZGUgPG5ldC9ibHVl
dG9vdGgvaGNpX2NvcmUuaD4NCj4gKyNpbmNsdWRlICJidHVzYi5oIg0KPiAgDQo+ICAjZGVmaW5l
IFZFUlNJT04gIjAuNiINCj4gIA0KPiBAQCAtMzksMTQgKzQwLDU5IEBAIHN0YXRpYyBib29sIHJl
c2V0ID0gMTsNCj4gIA0KPiAgc3RhdGljIHN0cnVjdCB1c2JfZHJpdmVyIGJ0dXNiX2RyaXZlcjsN
Cj4gIA0KPiAtI2RlZmluZSBCVFVTQl9JR05PUkUJCTB4MDENCj4gLSNkZWZpbmUgQlRVU0JfRElH
SUFOU1dFUgkweDAyDQo+IC0jZGVmaW5lIEJUVVNCX0NTUgkJMHgwNA0KPiAtI2RlZmluZSBCVFVT
Ql9TTklGRkVSCQkweDA4DQo+IC0jZGVmaW5lIEJUVVNCX0JDTTkyMDM1CQkweDEwDQo+IC0jZGVm
aW5lIEJUVVNCX0JST0tFTl9JU09DCTB4MjANCj4gLSNkZWZpbmUgQlRVU0JfV1JPTkdfU0NPX01U
VQkweDQwDQo+IC0jZGVmaW5lIEJUVVNCX0FUSDMwMTIJCTB4ODANCj4gKy8qDQo+ICsgKiBDcmVh
dGUgYnR1c2JfZHJpdmVyX2luZm8gc3RydWN0IGZvciBlYWNoIGRyaXZlcl9pbmZvIGZsYWdzIHVz
ZWQgYnkNCj4gKyAqIGJsYWNrbGlzdCBzaW5jZSB2ZW5kb3IncyBidHVzYiBkcml2ZXIgd2lsbCBy
ZXR1cm4gYnR1c2JfZHJpdmVyX2luZm8gc3RydWN0Lg0KPiArICovDQo+ICsNCj4gKy8qDQo+ICsg
KiBpZiB0aGUgZGV2aWNlIGlzIHNldCB0byB0aGlzLCB0aGlzIG1lbmFzIHRoYXQgdGhlIGRldmlj
ZSBpcyANCj4gK2dlbmVyaWMgYW5kDQo+ICsgKiBkb2Vzbid0IHJlcXVpcmUgYW55IHZlbmRvciBz
cGVjaWZpYyBoYW5kbGluZyAgKi8gc3RhdGljIGNvbnN0IA0KPiArc3RydWN0IGJ0dXNiX2RyaXZl
cl9pbmZvIGdlbmVyaWMgPSB7DQo+ICsJLmRlc2NyaXB0aW9uCT0gIkJUVVNCIEdlbmVyaWMiLA0K
PiArCS5mbGFncwkJPSBCVFVTQl9HRU5FUklDLA0KPiArfTsNCj4gKw0KPiArc3RhdGljIGNvbnN0
IHN0cnVjdCBidHVzYl9kcml2ZXJfaW5mbyBpZ25vcmUgPSB7DQo+ICsJLmRlc2NyaXB0aW9uCT0g
IkJUVVNCIElnbm9yZSIsDQo+ICsJLmZsYWdzCQk9IEJUVVNCX0lHTk9SRSwNCj4gK307DQoNCj4+
IEkgbGlrZSB0aGUgZWZmb3J0LCBidXQgSSB0aGluayB5b3Ugd2VudCBhIGxpdHRsZSBiaXQgdG9v
IGZhciBoZXJlLiBGb3IgdGhlc2Ugc2ltcGxlIG9uZXMsIHdlIGNhbiBlYXNpbHkga2VlcCBvdXIg
c2ltcGxlIGJsYWNrbGlzdC4gSXQga2VlcHMgdGhlIGNvZGUgbW9yZSByZWFkYWJsZSB0aGFuIHRo
aXMgcGFydC4gQnV0IEkgZG8gYXBwcmVjaWF0ZSB0aGUgYXR0ZW1wdCBpbiB1bmlmeWluZyB0aGlz
Lg0KDQoNCj4gKw0KPiArc3RhdGljIGNvbnN0IHN0cnVjdCBidHVzYl9kcml2ZXJfaW5mbyBkaWdp
YW5zd2VyID0gew0KPiArCS5kZXNjcmlwdGlvbgk9ICJCVFVTQiBESUdJQU5TV0VSIiwNCj4gKwku
ZmxhZ3MJCT0gQlRVU0JfRElHSUFOU1dFUiwNCj4gK307DQo+ICsNCj4gK3N0YXRpYyBjb25zdCBz
dHJ1Y3QgYnR1c2JfZHJpdmVyX2luZm8gY3NyID0gew0KPiArCS5kZXNjcmlwdGlvbgk9ICJCVFVT
QiBDU1IiLA0KPiArCS5mbGFncwkJPSBCVFVTQl9DU1IsDQo+ICt9Ow0KPiArDQo+ICtzdGF0aWMg
Y29uc3Qgc3RydWN0IGJ0dXNiX2RyaXZlcl9pbmZvIHNuaWZmZXIgPSB7DQo+ICsJLmRlc2NyaXB0
aW9uCT0gIkJUVVNCIFNuaWZmZXIiLA0KPiArCS5mbGFncwkJPSBCVFVTQl9TTklGRkVSLA0KPiAr
fTsNCj4gKw0KPiArc3RhdGljIGNvbnN0IHN0cnVjdCBidHVzYl9kcml2ZXJfaW5mbyBiY205MjAz
NSA9IHsNCj4gKwkuZGVzY3JpcHRpb24JPSAiQlRVU0IgQkNNOTIwMzUiLA0KPiArCS5mbGFncwkJ
PSBCVFVTQl9CQ005MjAzNSwNCj4gK307DQo+ICsNCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgYnR1
c2JfZHJpdmVyX2luZm8gYnJva2VuX2lzb2MgPSB7DQo+ICsJLmRlc2NyaXB0aW9uCT0gIkJUVVNC
IEJyb2tlbiBJU09DIiwNCj4gKwkuZmxhZ3MJCT0gQlRVU0JfQlJPS0VOX0lTT0MsDQo+ICt9Ow0K
PiArDQo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGJ0dXNiX2RyaXZlcl9pbmZvIHdyb25nX3Njb19t
dHUgPSB7DQo+ICsJLmRlc2NyaXB0aW9uCT0gIkJUVVNCIFdyb25nIFNDTyBNVFUiLA0KPiArCS5m
bGFncwkJPSBCVFVTQl9XUk9OR19TQ09fTVRVLA0KPiArfTsNCj4gKw0KPiArc3RhdGljIGNvbnN0
IHN0cnVjdCBidHVzYl9kcml2ZXJfaW5mbyBhdGgzMDEyID0gew0KPiArCS5kZXNjcmlwdGlvbgk9
ICJCVFVTQiBBdGgzMDEyIiwNCj4gKwkuZmxhZ3MJCT0gQlRVU0JfQVRIMzAxMiwNCj4gK307DQo+
ICANCj4gIHN0YXRpYyBzdHJ1Y3QgdXNiX2RldmljZV9pZCBidHVzYl90YWJsZVtdID0gew0KPiAg
CS8qIEdlbmVyaWMgQmx1ZXRvb3RoIFVTQiBkZXZpY2UgKi8NCj4gQEAgLTEwNSw5MCArMTUxLDg5
IEBAIHN0YXRpYyBzdHJ1Y3QgdXNiX2RldmljZV9pZCBidHVzYl90YWJsZVtdID0gew0KPiAgDQo+
ICAJeyB9CS8qIFRlcm1pbmF0aW5nIGVudHJ5ICovDQo+ICB9Ow0KPiAtDQo+ICBNT0RVTEVfREVW
SUNFX1RBQkxFKHVzYiwgYnR1c2JfdGFibGUpOw0KPiAgDQo+ICBzdGF0aWMgc3RydWN0IHVzYl9k
ZXZpY2VfaWQgYmxhY2tsaXN0X3RhYmxlW10gPSB7DQo+ICAJLyogQ1NSIEJsdWVDb3JlIGRldmlj
ZXMgKi8NCj4gLQl7IFVTQl9ERVZJQ0UoMHgwYTEyLCAweDAwMDEpLCAuZHJpdmVyX2luZm8gPSBC
VFVTQl9DU1IgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwYTEyLCAweDAwMDEpLCAuZHJpdmVyX2lu
Zm8gPSAodW5zaWduZWQgbG9uZykgJmNzciB9LA0KDQo+PiBLZWVwIHRoZSBibGFja2xpc3RfdGFi
bGUgYXMgaXQgaXMuIFRoZSBpbXBvcnRhbnQgdGFibGUgdG8gbW9kaWZ5IGlzIGJ0dXNiX3RhYmxl
IGFuZCB1c2UgYSBjb21tb24gZHJpdmVyX2luZm8gdGhhdCB3aWxsIGJlIHNoYXJlZCBiZXR3ZWVu
IGRyaXZlcnMuDQoNCj4+IFRoYXQgd291bGQgYWxzbyBtYWtlIGl0IHNpbXBsZSB0byBqdXN0IGFk
ZCBCVFVTQl9JR05PUkUgb3IgYSBuZXcgQlRVU0JfVkVORE9SIGZsYWcgdG8gY2FsbCBvdXQgdGhl
IGRyaXZlcnMgdGhhdCBoYXZlIGEgc2VwYXJhdGUgZHJpdmVyIHdpdGggYSB2ZW5kb3IgaW5pdCBm
dW5jdGlvbiwgYnV0IHdvdWxkIG1hdGNoID4+IHRoZSBCbHVldG9vdGggZ2VuZXJhbCBVU0IgZGVz
Y3JpcHRvcnMuDQoNCkkgbG9va2VkIGF0IHVzYm5ldCBtaW5pZHJpdmVyIGFzIHlvdSBzdWdnZXN0
ZWQuICBJZiB3ZSBkbyBhIHNpbWlsYXIgc2NoZW1lIHN1Y2ggdGhhdCBidHVzYl9wcm9iZSgpIGlu
dm9rZXMgdGhlIG1pbmlfZHJpdmVyJ3MgYmluZCgpL3VuYmluZCgpIHRoZW4gYnR1c2IncyB1c2Fn
ZSBvZiBkcml2ZXJfaW5mbyB3aWxsIG5lZWQgdG8gY2hhbmdlIGZyb20gc3RvcmluZyBmbGFncyAo
ZXg6IEJUVVNCX0lHTk9SRSkgYW5kIGNoYW5nZSB0byBzdG9yZSAic3RhdGljIGNvbnN0IHN0cnVj
dCIgd2hlcmUgaXQgaG9sZHMgYSBzdHJ1Y3QgY29udGFpbmluZyB0aGUgbWluaS1kcml2ZXIncyBi
aW5kL3VuYmluZCBmdW5jdGlvbnMgKGp1c3QgbGlrZSB1c2JuZXQgbWluaWRyaXZlcikuICAgQXJl
IHlvdSBnb29kIHdpdGggdGhpcyBjaGFuZ2U/ICBJIGFsc28gd2FudCB0byBtZW50aW9uIHRoYXQg
aW4gdGhlIHBhdGNoIGNvbnRhaW5pbmcgdGhlIEJUIFVTQiBtaW5pIGRyaXZlciB0ZW1wbGF0ZSwg
aXQgYWxyZWFkeSBoYXMgaXRzIG93biBtb2R1bGVfdXNiX2RyaXZlcigpIHNlY3Rpb24gd2l0aCBp
dHMgVklEL1BJRCBsaXN0ZWQuDQoNCg0KPj4gVGhlbiBvdmVyIHRpbWUsIHdlIGNhbiBtb3ZlIHRo
ZSBCVFVTQl9CQ005MjAzNSBmb3IgZXhhbXBsZSBpbnRvIGl0cyBzZXBhcmF0ZSBkcml2ZXIuIEFu
ZCBhbHNvIGRlYWwgd2l0aCBjbGVhbmluZyB1cCBhbGwgdGhlIG90aGVyIEJyb2FkY29tIHNwZWNp
YWx0aWVzLg0KDQo+ICANCj4gIAkvKiBCcm9hZGNvbSBCQ00yMDMzIHdpdGhvdXQgZmlybXdhcmUg
Ki8NCj4gLQl7IFVTQl9ERVZJQ0UoMHgwYTVjLCAweDIwMzMpLCAuZHJpdmVyX2luZm8gPSBCVFVT
Ql9JR05PUkUgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwYTVjLCAweDIwMzMpLCAuZHJpdmVyX2lu
Zm8gPSAodW5zaWduZWQgbG9uZykgJmlnbm9yZSANCj4gK30sDQo+ICANCj4gIAkvKiBBdGhlcm9z
IDMwMTEgd2l0aCBzZmxhc2ggZmlybXdhcmUgKi8NCj4gLQl7IFVTQl9ERVZJQ0UoMHgwY2YzLCAw
eDMwMDIpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9JR05PUkUgfSwNCj4gLQl7IFVTQl9ERVZJQ0Uo
MHgwY2YzLCAweGUwMTkpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9JR05PUkUgfSwNCj4gLQl7IFVT
Ql9ERVZJQ0UoMHgxM2QzLCAweDMzMDQpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9JR05PUkUgfSwN
Cj4gLQl7IFVTQl9ERVZJQ0UoMHgwOTMwLCAweDAyMTUpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9J
R05PUkUgfSwNCj4gLQl7IFVTQl9ERVZJQ0UoMHgwNDg5LCAweGUwM2QpLCAuZHJpdmVyX2luZm8g
PSBCVFVTQl9JR05PUkUgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwY2YzLCAweDMwMDIpLCAuZHJp
dmVyX2luZm8gPSAodW5zaWduZWQgbG9uZykgJmlnbm9yZSB9LA0KPiArCXsgVVNCX0RFVklDRSgw
eDBjZjMsIDB4ZTAxOSksIC5kcml2ZXJfaW5mbyA9ICh1bnNpZ25lZCBsb25nKSAmaWdub3JlIH0s
DQo+ICsJeyBVU0JfREVWSUNFKDB4MTNkMywgMHgzMzA0KSwgLmRyaXZlcl9pbmZvID0gKHVuc2ln
bmVkIGxvbmcpICZpZ25vcmUgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwOTMwLCAweDAyMTUpLCAu
ZHJpdmVyX2luZm8gPSAodW5zaWduZWQgbG9uZykgJmlnbm9yZSB9LA0KPiArCXsgVVNCX0RFVklD
RSgweDA0ODksIDB4ZTAzZCksIC5kcml2ZXJfaW5mbyA9ICh1bnNpZ25lZCBsb25nKSAmaWdub3Jl
IA0KPiArfSwNCj4gIA0KPiAgCS8qIEF0aGVyb3MgQVI5Mjg1IE1hbGJlYyB3aXRoIHNmbGFzaCBm
aXJtd2FyZSAqLw0KPiAtCXsgVVNCX0RFVklDRSgweDAzZjAsIDB4MzExZCksIC5kcml2ZXJfaW5m
byA9IEJUVVNCX0lHTk9SRSB9LA0KPiArCXsgVVNCX0RFVklDRSgweDAzZjAsIDB4MzExZCksIC5k
cml2ZXJfaW5mbyA9ICh1bnNpZ25lZCBsb25nKSAmaWdub3JlIA0KPiArfSwNCj4gIA0KPiAgCS8q
IEF0aGVyb3MgMzAxMiB3aXRoIHNmbGFzaCBmaXJtd2FyZSAqLw0KPiAtCXsgVVNCX0RFVklDRSgw
eDBjZjMsIDB4MzAwNCksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX0FUSDMwMTIgfSwNCj4gLQl7IFVT
Ql9ERVZJQ0UoMHgwY2YzLCAweDMxMWQpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9BVEgzMDEyIH0s
DQo+IC0JeyBVU0JfREVWSUNFKDB4MTNkMywgMHgzMzc1KSwgLmRyaXZlcl9pbmZvID0gQlRVU0Jf
QVRIMzAxMiB9LA0KPiAtCXsgVVNCX0RFVklDRSgweDA0Y2EsIDB4MzAwNSksIC5kcml2ZXJfaW5m
byA9IEJUVVNCX0FUSDMwMTIgfSwNCj4gLQl7IFVTQl9ERVZJQ0UoMHgxM2QzLCAweDMzNjIpLCAu
ZHJpdmVyX2luZm8gPSBCVFVTQl9BVEgzMDEyIH0sDQo+IC0JeyBVU0JfREVWSUNFKDB4MGNmMywg
MHhlMDA0KSwgLmRyaXZlcl9pbmZvID0gQlRVU0JfQVRIMzAxMiB9LA0KPiAtCXsgVVNCX0RFVklD
RSgweDA5MzAsIDB4MDIxOSksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX0FUSDMwMTIgfSwNCj4gKwl7
IFVTQl9ERVZJQ0UoMHgwY2YzLCAweDMwMDQpLCAuZHJpdmVyX2luZm8gPSAodW5zaWduZWQgbG9u
ZykgJmF0aDMwMTIgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwY2YzLCAweDMxMWQpLCAuZHJpdmVy
X2luZm8gPSAodW5zaWduZWQgbG9uZykgJmF0aDMwMTIgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgx
M2QzLCAweDMzNzUpLCAuZHJpdmVyX2luZm8gPSAodW5zaWduZWQgbG9uZykgJmF0aDMwMTIgfSwN
Cj4gKwl7IFVTQl9ERVZJQ0UoMHgwNGNhLCAweDMwMDUpLCAuZHJpdmVyX2luZm8gPSAodW5zaWdu
ZWQgbG9uZykgJmF0aDMwMTIgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgxM2QzLCAweDMzNjIpLCAu
ZHJpdmVyX2luZm8gPSAodW5zaWduZWQgbG9uZykgJmF0aDMwMTIgfSwNCj4gKwl7IFVTQl9ERVZJ
Q0UoMHgwY2YzLCAweGUwMDQpLCAuZHJpdmVyX2luZm8gPSAodW5zaWduZWQgbG9uZykgJmF0aDMw
MTIgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwOTMwLCAweDAyMTkpLCAuZHJpdmVyX2luZm8gPSAo
dW5zaWduZWQgbG9uZykgDQo+ICsmYXRoMzAxMiB9LA0KPiAgDQo+ICAJLyogQXRoZXJvcyBBUjVC
QlUxMiB3aXRoIHNmbGFzaCBmaXJtd2FyZSAqLw0KPiAtCXsgVVNCX0RFVklDRSgweDA0ODksIDB4
ZTAyYyksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX0lHTk9SRSB9LA0KPiArCXsgVVNCX0RFVklDRSgw
eDA0ODksIDB4ZTAyYyksIC5kcml2ZXJfaW5mbyA9ICh1bnNpZ25lZCBsb25nKSAmaWdub3JlIA0K
PiArfSwNCj4gIA0KPiAgCS8qIEF0aGVyb3MgQVI1QkJVMTIgd2l0aCBzZmxhc2ggZmlybXdhcmUg
Ki8NCj4gLQl7IFVTQl9ERVZJQ0UoMHgwNDg5LCAweGUwM2MpLCAuZHJpdmVyX2luZm8gPSBCVFVT
Ql9BVEgzMDEyIH0sDQo+ICsJeyBVU0JfREVWSUNFKDB4MDQ4OSwgMHhlMDNjKSwgLmRyaXZlcl9p
bmZvID0gKHVuc2lnbmVkIGxvbmcpIA0KPiArJmF0aDMwMTIgfSwNCj4gIA0KPiAgCS8qIEJyb2Fk
Y29tIEJDTTIwMzUgKi8NCj4gLQl7IFVTQl9ERVZJQ0UoMHgwYTVjLCAweDIwMzUpLCAuZHJpdmVy
X2luZm8gPSBCVFVTQl9XUk9OR19TQ09fTVRVIH0sDQo+IC0JeyBVU0JfREVWSUNFKDB4MGE1Yywg
MHgyMDBhKSwgLmRyaXZlcl9pbmZvID0gQlRVU0JfV1JPTkdfU0NPX01UVSB9LA0KPiAtCXsgVVNC
X0RFVklDRSgweDBhNWMsIDB4MjAwOSksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX0JDTTkyMDM1IH0s
DQo+ICsJeyBVU0JfREVWSUNFKDB4MGE1YywgMHgyMDM1KSwgLmRyaXZlcl9pbmZvID0gKHVuc2ln
bmVkIGxvbmcpICZ3cm9uZ19zY29fbXR1IH0sDQo+ICsJeyBVU0JfREVWSUNFKDB4MGE1YywgMHgy
MDBhKSwgLmRyaXZlcl9pbmZvID0gKHVuc2lnbmVkIGxvbmcpICZ3cm9uZ19zY29fbXR1IH0sDQo+
ICsJeyBVU0JfREVWSUNFKDB4MGE1YywgMHgyMDA5KSwgLmRyaXZlcl9pbmZvID0gKHVuc2lnbmVk
IGxvbmcpIA0KPiArJmJjbTkyMDM1IH0sDQo+ICANCj4gIAkvKiBCcm9hZGNvbSBCQ00yMDQ1ICov
DQo+IC0JeyBVU0JfREVWSUNFKDB4MGE1YywgMHgyMDM5KSwgLmRyaXZlcl9pbmZvID0gQlRVU0Jf
V1JPTkdfU0NPX01UVSB9LA0KPiAtCXsgVVNCX0RFVklDRSgweDBhNWMsIDB4MjEwMSksIC5kcml2
ZXJfaW5mbyA9IEJUVVNCX1dST05HX1NDT19NVFUgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwYTVj
LCAweDIwMzkpLCAuZHJpdmVyX2luZm8gPSAodW5zaWduZWQgbG9uZykgJndyb25nX3Njb19tdHUg
fSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwYTVjLCAweDIxMDEpLCAuZHJpdmVyX2luZm8gPSAodW5z
aWduZWQgbG9uZykgDQo+ICsmd3Jvbmdfc2NvX210dSB9LA0KPiAgDQo+ICAJLyogSUJNL0xlbm92
byBUaGlua1BhZCB3aXRoIEJyb2FkY29tIGNoaXAgKi8NCj4gLQl7IFVTQl9ERVZJQ0UoMHgwYTVj
LCAweDIwMWUpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9XUk9OR19TQ09fTVRVIH0sDQo+IC0JeyBV
U0JfREVWSUNFKDB4MGE1YywgMHgyMTEwKSwgLmRyaXZlcl9pbmZvID0gQlRVU0JfV1JPTkdfU0NP
X01UVSB9LA0KPiArCXsgVVNCX0RFVklDRSgweDBhNWMsIDB4MjAxZSksIC5kcml2ZXJfaW5mbyA9
ICh1bnNpZ25lZCBsb25nKSAmd3Jvbmdfc2NvX210dSB9LA0KPiArCXsgVVNCX0RFVklDRSgweDBh
NWMsIDB4MjExMCksIC5kcml2ZXJfaW5mbyA9ICh1bnNpZ25lZCBsb25nKSANCj4gKyZ3cm9uZ19z
Y29fbXR1IH0sDQo+ICANCj4gIAkvKiBIUCBsYXB0b3Agd2l0aCBCcm9hZGNvbSBjaGlwICovDQo+
IC0JeyBVU0JfREVWSUNFKDB4MDNmMCwgMHgxNzFkKSwgLmRyaXZlcl9pbmZvID0gQlRVU0JfV1JP
TkdfU0NPX01UVSB9LA0KPiArCXsgVVNCX0RFVklDRSgweDAzZjAsIDB4MTcxZCksIC5kcml2ZXJf
aW5mbyA9ICh1bnNpZ25lZCBsb25nKSANCj4gKyZ3cm9uZ19zY29fbXR1IH0sDQo+ICANCj4gIAkv
KiBEZWxsIGxhcHRvcCB3aXRoIEJyb2FkY29tIGNoaXAgKi8NCj4gLQl7IFVTQl9ERVZJQ0UoMHg0
MTNjLCAweDgxMjYpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9XUk9OR19TQ09fTVRVIH0sDQo+ICsJ
eyBVU0JfREVWSUNFKDB4NDEzYywgMHg4MTI2KSwgLmRyaXZlcl9pbmZvID0gKHVuc2lnbmVkIGxv
bmcpIA0KPiArJndyb25nX3Njb19tdHUgfSwNCj4gIA0KPiAgCS8qIERlbGwgV2lyZWxlc3MgMzcw
IGFuZCA0MTAgZGV2aWNlcyAqLw0KPiAtCXsgVVNCX0RFVklDRSgweDQxM2MsIDB4ODE1MiksIC5k
cml2ZXJfaW5mbyA9IEJUVVNCX1dST05HX1NDT19NVFUgfSwNCj4gLQl7IFVTQl9ERVZJQ0UoMHg0
MTNjLCAweDgxNTYpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9XUk9OR19TQ09fTVRVIH0sDQo+ICsJ
eyBVU0JfREVWSUNFKDB4NDEzYywgMHg4MTUyKSwgLmRyaXZlcl9pbmZvID0gKHVuc2lnbmVkIGxv
bmcpICZ3cm9uZ19zY29fbXR1IH0sDQo+ICsJeyBVU0JfREVWSUNFKDB4NDEzYywgMHg4MTU2KSwg
LmRyaXZlcl9pbmZvID0gKHVuc2lnbmVkIGxvbmcpIA0KPiArJndyb25nX3Njb19tdHUgfSwNCj4g
IA0KPiAgCS8qIEJlbGtpbiBGOFQwMTIgYW5kIEY4VDAxMyBkZXZpY2VzICovDQo+IC0JeyBVU0Jf
REVWSUNFKDB4MDUwZCwgMHgwMDEyKSwgLmRyaXZlcl9pbmZvID0gQlRVU0JfV1JPTkdfU0NPX01U
VSB9LA0KPiAtCXsgVVNCX0RFVklDRSgweDA1MGQsIDB4MDAxMyksIC5kcml2ZXJfaW5mbyA9IEJU
VVNCX1dST05HX1NDT19NVFUgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwNTBkLCAweDAwMTIpLCAu
ZHJpdmVyX2luZm8gPSAodW5zaWduZWQgbG9uZykgJndyb25nX3Njb19tdHUgfSwNCj4gKwl7IFVT
Ql9ERVZJQ0UoMHgwNTBkLCAweDAwMTMpLCAuZHJpdmVyX2luZm8gPSAodW5zaWduZWQgbG9uZykg
DQo+ICsmd3Jvbmdfc2NvX210dSB9LA0KPiAgDQo+ICAJLyogQXN1cyBXTC1CVEQyMDIgZGV2aWNl
ICovDQo+IC0JeyBVU0JfREVWSUNFKDB4MGIwNSwgMHgxNzE1KSwgLmRyaXZlcl9pbmZvID0gQlRV
U0JfV1JPTkdfU0NPX01UVSB9LA0KPiArCXsgVVNCX0RFVklDRSgweDBiMDUsIDB4MTcxNSksIC5k
cml2ZXJfaW5mbyA9ICh1bnNpZ25lZCBsb25nKSANCj4gKyZ3cm9uZ19zY29fbXR1IH0sDQo+ICAN
Cj4gIAkvKiBLZW5zaW5ndG9uIEJsdWV0b290aCBVU0IgYWRhcHRlciAqLw0KPiAtCXsgVVNCX0RF
VklDRSgweDA0N2QsIDB4MTA1ZSksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX1dST05HX1NDT19NVFUg
fSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwNDdkLCAweDEwNWUpLCAuZHJpdmVyX2luZm8gPSAodW5z
aWduZWQgbG9uZykgDQo+ICsmd3Jvbmdfc2NvX210dSB9LA0KPiAgDQo+ICAJLyogUlRYIFRlbGVj
b20gYmFzZWQgYWRhcHRlcnMgd2l0aCBidWdneSBTQ08gc3VwcG9ydCAqLw0KPiAtCXsgVVNCX0RF
VklDRSgweDA0MDAsIDB4MDgwNyksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX0JST0tFTl9JU09DIH0s
DQo+IC0JeyBVU0JfREVWSUNFKDB4MDQwMCwgMHgwODBhKSwgLmRyaXZlcl9pbmZvID0gQlRVU0Jf
QlJPS0VOX0lTT0MgfSwNCj4gKwl7IFVTQl9ERVZJQ0UoMHgwNDAwLCAweDA4MDcpLCAuZHJpdmVy
X2luZm8gPSAodW5zaWduZWQgbG9uZykgJmJyb2tlbl9pc29jIH0sDQo+ICsJeyBVU0JfREVWSUNF
KDB4MDQwMCwgMHgwODBhKSwgLmRyaXZlcl9pbmZvID0gKHVuc2lnbmVkIGxvbmcpIA0KPiArJmJy
b2tlbl9pc29jIH0sDQo+ICANCj4gIAkvKiBDT05XSVNFIFRlY2hub2xvZ3kgYmFzZWQgYWRhcHRl
cnMgd2l0aCBidWdneSBTQ08gc3VwcG9ydCAqLw0KPiAtCXsgVVNCX0RFVklDRSgweDBlNWUsIDB4
NjYyMiksIC5kcml2ZXJfaW5mbyA9IEJUVVNCX0JST0tFTl9JU09DIH0sDQo+ICsJeyBVU0JfREVW
SUNFKDB4MGU1ZSwgMHg2NjIyKSwgLmRyaXZlcl9pbmZvID0gKHVuc2lnbmVkIGxvbmcpIA0KPiAr
JmJyb2tlbl9pc29jIH0sDQo+ICANCj4gIAkvKiBEaWdpYW5zd2VyIGRldmljZXMgKi8NCj4gLQl7
IFVTQl9ERVZJQ0UoMHgwOGZkLCAweDAwMDEpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9ESUdJQU5T
V0VSIH0sDQo+IC0JeyBVU0JfREVWSUNFKDB4MDhmZCwgMHgwMDAyKSwgLmRyaXZlcl9pbmZvID0g
QlRVU0JfSUdOT1JFIH0sDQo+ICsJeyBVU0JfREVWSUNFKDB4MDhmZCwgMHgwMDAxKSwgLmRyaXZl
cl9pbmZvID0gKHVuc2lnbmVkIGxvbmcpICZkaWdpYW5zd2VyIH0sDQo+ICsJeyBVU0JfREVWSUNF
KDB4MDhmZCwgMHgwMDAyKSwgLmRyaXZlcl9pbmZvID0gKHVuc2lnbmVkIGxvbmcpICZpZ25vcmUg
DQo+ICt9LA0KPiAgDQo+ICAJLyogQ1NSIEJsdWVDb3JlIEJsdWV0b290aCBTbmlmZmVyICovDQo+
IC0JeyBVU0JfREVWSUNFKDB4MGExMiwgMHgwMDAyKSwgLmRyaXZlcl9pbmZvID0gQlRVU0JfU05J
RkZFUiB9LA0KPiArCXsgVVNCX0RFVklDRSgweDBhMTIsIDB4MDAwMiksIC5kcml2ZXJfaW5mbyA9
ICh1bnNpZ25lZCBsb25nKSANCj4gKyZzbmlmZmVyIH0sDQo+ICANCj4gIAkvKiBGcm9udGxpbmUg
Q29tUHJvYmUgQmx1ZXRvb3RoIFNuaWZmZXIgKi8NCj4gLQl7IFVTQl9ERVZJQ0UoMHgxNmQzLCAw
eDAwMDIpLCAuZHJpdmVyX2luZm8gPSBCVFVTQl9TTklGRkVSIH0sDQo+ICsJeyBVU0JfREVWSUNF
KDB4MTZkMywgMHgwMDAyKSwgLmRyaXZlcl9pbmZvID0gKHVuc2lnbmVkIGxvbmcpIA0KPiArJnNu
aWZmZXIgfSwNCj4gIA0KPiAgCXsgfQkvKiBUZXJtaW5hdGluZyBlbnRyeSAqLw0KPiAgfTsNCj4g
QEAgLTkxMCwxMiArOTU1LDEyIEBAIHN0YXRpYyB2b2lkIGJ0dXNiX3dha2VyKHN0cnVjdCB3b3Jr
X3N0cnVjdCAqd29yaykNCj4gIAl1c2JfYXV0b3BtX3B1dF9pbnRlcmZhY2UoZGF0YS0+aW50Zik7
DQo+ICB9DQo+ICANCj4gLXN0YXRpYyBpbnQgYnR1c2JfcHJvYmUoc3RydWN0IHVzYl9pbnRlcmZh
Y2UgKmludGYsDQo+IC0JCQkJY29uc3Qgc3RydWN0IHVzYl9kZXZpY2VfaWQgKmlkKQ0KPiAraW50
IGJ0dXNiX3Byb2JlKHN0cnVjdCB1c2JfaW50ZXJmYWNlICppbnRmLCBjb25zdCBzdHJ1Y3QgDQo+
ICt1c2JfZGV2aWNlX2lkICppZCkNCj4gIHsNCj4gIAlzdHJ1Y3QgdXNiX2VuZHBvaW50X2Rlc2Ny
aXB0b3IgKmVwX2Rlc2M7DQo+ICAJc3RydWN0IGJ0dXNiX2RhdGEgKmRhdGE7DQo+ICAJc3RydWN0
IGhjaV9kZXYgKmhkZXY7DQo+ICsJc3RydWN0IGJ0dXNiX2RyaXZlcl9pbmZvICppbmZvOw0KPiAg
CWludCBpLCBlcnI7DQo+ICANCj4gIAlCVF9EQkcoImludGYgJXAgaWQgJXAiLCBpbnRmLCBpZCk7
DQo+IEBAIC05MzEsMTkgKzk3NiwyOCBAQCBzdGF0aWMgaW50IGJ0dXNiX3Byb2JlKHN0cnVjdCB1
c2JfaW50ZXJmYWNlICppbnRmLA0KPiAgCQkJaWQgPSBtYXRjaDsNCj4gIAl9DQo+ICANCj4gLQlp
ZiAoaWQtPmRyaXZlcl9pbmZvID09IEJUVVNCX0lHTk9SRSkNCj4gKwkvKg0KPiArCSAqIE1ha2Ug
c3VyZSB0aGUgZHJpdmVyX2luZm8gaXMgbm90IG51bGwgb3IgMCBiZWNhdXNlIHRoZSBjb2RlIGJl
bG93DQo+ICsJICogbmVlZCB0byBhY2Nlc3MgdGhlIGZsYWdzDQo+ICsJICovDQo+ICsJaWYgKCFp
ZC0+ZHJpdmVyX2luZm8pDQo+ICsJCWluZm8gPSAoc3RydWN0IGJ0dXNiX2RyaXZlcl9pbmZvICop
ICZnZW5lcmljOw0KPiArCWVsc2UNCj4gKwkJaW5mbyA9IChzdHJ1Y3QgYnR1c2JfZHJpdmVyX2lu
Zm8gKikgaWQtPmRyaXZlcl9pbmZvOw0KPiArDQo+ICsJaWYgKGluZm8tPmZsYWdzID09IEJUVVNC
X0lHTk9SRSkNCj4gIAkJcmV0dXJuIC1FTk9ERVY7DQo+ICANCj4gLQlpZiAoaWdub3JlX2RnYSAm
JiBpZC0+ZHJpdmVyX2luZm8gJiBCVFVTQl9ESUdJQU5TV0VSKQ0KPiArCWlmIChpZ25vcmVfZGdh
ICYmIChpbmZvLT5mbGFncyAmIEJUVVNCX0RJR0lBTlNXRVIpKQ0KPiAgCQlyZXR1cm4gLUVOT0RF
VjsNCj4gIA0KPiAtCWlmIChpZ25vcmVfY3NyICYmIGlkLT5kcml2ZXJfaW5mbyAmIEJUVVNCX0NT
UikNCj4gKwlpZiAoaWdub3JlX2NzciAmJiAoaW5mby0+ZmxhZ3MgJiBCVFVTQl9DU1IpKQ0KPiAg
CQlyZXR1cm4gLUVOT0RFVjsNCj4gIA0KPiAtCWlmIChpZ25vcmVfc25pZmZlciAmJiBpZC0+ZHJp
dmVyX2luZm8gJiBCVFVTQl9TTklGRkVSKQ0KPiArCWlmIChpZ25vcmVfc25pZmZlciAmJiAoaW5m
by0+ZmxhZ3MgJiBCVFVTQl9TTklGRkVSKSkNCj4gIAkJcmV0dXJuIC1FTk9ERVY7DQo+ICANCj4g
LQlpZiAoaWQtPmRyaXZlcl9pbmZvICYgQlRVU0JfQVRIMzAxMikgew0KPiArCWlmIChpbmZvLT5m
bGFncyAmIEJUVVNCX0FUSDMwMTIpIHsNCj4gIAkJc3RydWN0IHVzYl9kZXZpY2UgKnVkZXYgPSBp
bnRlcmZhY2VfdG9fdXNiZGV2KGludGYpOw0KPiAgDQo+ICAJCS8qIE9sZCBmaXJtd2FyZSB3b3Vs
ZCBvdGhlcndpc2UgbGV0IGF0aDNrIGRyaXZlciBsb2FkIEBAIC0xMDEyLDI2IA0KPiArMTA2Niwz
MCBAQCBzdGF0aWMgaW50IGJ0dXNiX3Byb2JlKHN0cnVjdCB1c2JfaW50ZXJmYWNlICppbnRmLA0K
PiAgCWhkZXYtPnNlbmQgICAgID0gYnR1c2Jfc2VuZF9mcmFtZTsNCj4gIAloZGV2LT5ub3RpZnkg
ICA9IGJ0dXNiX25vdGlmeTsNCj4gIA0KPiArCS8qIHZlbmRvciBzcGVjaWZpYyBkZXZpY2UgaW5p
dGlhbGl6YXRpb24gcm91dGluZXMgKi8NCj4gKwloZGV2LT52c2Rldl9pbml0ID0gaW5mby0+dnNk
ZXZfaW5pdDsNCj4gKwloZGV2LT52c2Rldl9ldmVudCA9IGluZm8tPnZzZGV2X2V2ZW50Ow0KPiAr
DQo+ICAJLyogSW50ZXJmYWNlIG51bWJlcnMgYXJlIGhhcmRjb2RlZCBpbiB0aGUgc3BlY2lmaWNh
dGlvbiAqLw0KPiAgCWRhdGEtPmlzb2MgPSB1c2JfaWZudW1fdG9faWYoZGF0YS0+dWRldiwgMSk7
DQo+ICANCj4gIAlpZiAoIXJlc2V0KQ0KPiAgCQlzZXRfYml0KEhDSV9RVUlSS19SRVNFVF9PTl9D
TE9TRSwgJmhkZXYtPnF1aXJrcyk7DQo+ICANCj4gLQlpZiAoZm9yY2Vfc2NvZml4IHx8IGlkLT5k
cml2ZXJfaW5mbyAmIEJUVVNCX1dST05HX1NDT19NVFUpIHsNCj4gKwlpZiAoZm9yY2Vfc2NvZml4
IHx8IChpbmZvLT5mbGFncyAmIEJUVVNCX1dST05HX1NDT19NVFUpKSB7DQo+ICAJCWlmICghZGlz
YWJsZV9zY29maXgpDQo+ICAJCQlzZXRfYml0KEhDSV9RVUlSS19GSVhVUF9CVUZGRVJfU0laRSwg
JmhkZXYtPnF1aXJrcyk7DQo+ICAJfQ0KPiAgDQo+IC0JaWYgKGlkLT5kcml2ZXJfaW5mbyAmIEJU
VVNCX0JST0tFTl9JU09DKQ0KPiArCWlmIChpbmZvLT5mbGFncyAmIEJUVVNCX0JST0tFTl9JU09D
KQ0KPiAgCQlkYXRhLT5pc29jID0gTlVMTDsNCj4gIA0KPiAtCWlmIChpZC0+ZHJpdmVyX2luZm8g
JiBCVFVTQl9ESUdJQU5TV0VSKSB7DQo+ICsJaWYgKGluZm8tPmZsYWdzICYgQlRVU0JfRElHSUFO
U1dFUikgew0KPiAgCQlkYXRhLT5jbWRyZXFfdHlwZSA9IFVTQl9UWVBFX1ZFTkRPUjsNCj4gIAkJ
c2V0X2JpdChIQ0lfUVVJUktfUkVTRVRfT05fQ0xPU0UsICZoZGV2LT5xdWlya3MpOw0KPiAgCX0N
Cj4gIA0KPiAtCWlmIChpZC0+ZHJpdmVyX2luZm8gJiBCVFVTQl9DU1IpIHsNCj4gKwlpZiAoaW5m
by0+ZmxhZ3MgJiBCVFVTQl9DU1IpIHsNCj4gIAkJc3RydWN0IHVzYl9kZXZpY2UgKnVkZXYgPSBk
YXRhLT51ZGV2Ow0KPiAgDQo+ICAJCS8qIE9sZCBmaXJtd2FyZSB3b3VsZCBvdGhlcndpc2UgZXhl
Y3V0ZSBVU0IgcmVzZXQgKi8gQEAgLTEwMzksNyANCj4gKzEwOTcsNyBAQCBzdGF0aWMgaW50IGJ0
dXNiX3Byb2JlKHN0cnVjdCB1c2JfaW50ZXJmYWNlICppbnRmLA0KPiAgCQkJc2V0X2JpdChIQ0lf
UVVJUktfUkVTRVRfT05fQ0xPU0UsICZoZGV2LT5xdWlya3MpOw0KPiAgCX0NCj4gIA0KPiAtCWlm
IChpZC0+ZHJpdmVyX2luZm8gJiBCVFVTQl9TTklGRkVSKSB7DQo+ICsJaWYgKGluZm8tPmZsYWdz
ICYgQlRVU0JfU05JRkZFUikgew0KPiAgCQlzdHJ1Y3QgdXNiX2RldmljZSAqdWRldiA9IGRhdGEt
PnVkZXY7DQo+ICANCj4gIAkJLyogTmV3IHNuaWZmZXIgZmlybXdhcmUgaGFzIGNyaXBwbGVkIEhD
SSBpbnRlcmZhY2UgKi8gQEAgLTEwNDksNyANCj4gKzExMDcsNyBAQCBzdGF0aWMgaW50IGJ0dXNi
X3Byb2JlKHN0cnVjdCB1c2JfaW50ZXJmYWNlICppbnRmLA0KPiAgCQlkYXRhLT5pc29jID0gTlVM
TDsNCj4gIAl9DQo+ICANCj4gLQlpZiAoaWQtPmRyaXZlcl9pbmZvICYgQlRVU0JfQkNNOTIwMzUp
IHsNCj4gKwlpZiAoaW5mby0+ZmxhZ3MgJiBCVFVTQl9CQ005MjAzNSkgew0KPiAgCQl1bnNpZ25l
ZCBjaGFyIGNtZFtdID0geyAweDNiLCAweGZjLCAweDAxLCAweDAwIH07DQo+ICAJCXN0cnVjdCBz
a19idWZmICpza2I7DQo+ICANCj4gQEAgLTEwNzksOCArMTEzNyw5IEBAIHN0YXRpYyBpbnQgYnR1
c2JfcHJvYmUoc3RydWN0IHVzYl9pbnRlcmZhY2UgDQo+ICppbnRmLA0KPiAgDQo+ICAJcmV0dXJu
IDA7DQo+ICB9DQo+ICtFWFBPUlRfU1lNQk9MX0dQTChidHVzYl9wcm9iZSk7DQo+ICANCj4gLXN0
YXRpYyB2b2lkIGJ0dXNiX2Rpc2Nvbm5lY3Qoc3RydWN0IHVzYl9pbnRlcmZhY2UgKmludGYpDQo+
ICt2b2lkIGJ0dXNiX2Rpc2Nvbm5lY3Qoc3RydWN0IHVzYl9pbnRlcmZhY2UgKmludGYpDQo+ICB7
DQo+ICAJc3RydWN0IGJ0dXNiX2RhdGEgKmRhdGEgPSB1c2JfZ2V0X2ludGZkYXRhKGludGYpOw0K
PiAgCXN0cnVjdCBoY2lfZGV2ICpoZGV2Ow0KPiBAQCAtMTEwNSw5ICsxMTY0LDEwIEBAIHN0YXRp
YyB2b2lkIGJ0dXNiX2Rpc2Nvbm5lY3Qoc3RydWN0IA0KPiB1c2JfaW50ZXJmYWNlICppbnRmKQ0K
PiAgDQo+ICAJaGNpX2ZyZWVfZGV2KGhkZXYpOw0KPiAgfQ0KPiArRVhQT1JUX1NZTUJPTF9HUEwo
YnR1c2JfZGlzY29ubmVjdCk7DQo+ICANCj4gICNpZmRlZiBDT05GSUdfUE0NCj4gLXN0YXRpYyBp
bnQgYnR1c2Jfc3VzcGVuZChzdHJ1Y3QgdXNiX2ludGVyZmFjZSAqaW50ZiwgcG1fbWVzc2FnZV90
IA0KPiBtZXNzYWdlKQ0KPiAraW50IGJ0dXNiX3N1c3BlbmQoc3RydWN0IHVzYl9pbnRlcmZhY2Ug
KmludGYsIHBtX21lc3NhZ2VfdCBtZXNzYWdlKQ0KPiAgew0KPiAgCXN0cnVjdCBidHVzYl9kYXRh
ICpkYXRhID0gdXNiX2dldF9pbnRmZGF0YShpbnRmKTsNCj4gIA0KPiBAQCAtMTEzMyw2ICsxMTkz
LDcgQEAgc3RhdGljIGludCBidHVzYl9zdXNwZW5kKHN0cnVjdCB1c2JfaW50ZXJmYWNlIA0KPiAq
aW50ZiwgcG1fbWVzc2FnZV90IG1lc3NhZ2UpDQo+ICANCj4gIAlyZXR1cm4gMDsNCj4gIH0NCj4g
K0VYUE9SVF9TWU1CT0xfR1BMKGJ0dXNiX3N1c3BlbmQpOw0KPiAgDQo+ICBzdGF0aWMgdm9pZCBw
bGF5X2RlZmVycmVkKHN0cnVjdCBidHVzYl9kYXRhICpkYXRhKSAgeyBAQCAtMTE0OSw3IA0KPiAr
MTIxMCw3IEBAIHN0YXRpYyB2b2lkIHBsYXlfZGVmZXJyZWQoc3RydWN0IGJ0dXNiX2RhdGEgKmRh
dGEpDQo+ICAJdXNiX3NjdXR0bGVfYW5jaG9yZWRfdXJicygmZGF0YS0+ZGVmZXJyZWQpOw0KPiAg
fQ0KPiAgDQo+IC1zdGF0aWMgaW50IGJ0dXNiX3Jlc3VtZShzdHJ1Y3QgdXNiX2ludGVyZmFjZSAq
aW50ZikNCj4gK2ludCBidHVzYl9yZXN1bWUoc3RydWN0IHVzYl9pbnRlcmZhY2UgKmludGYpDQo+
ICB7DQo+ICAJc3RydWN0IGJ0dXNiX2RhdGEgKmRhdGEgPSB1c2JfZ2V0X2ludGZkYXRhKGludGYp
Ow0KPiAgCXN0cnVjdCBoY2lfZGV2ICpoZGV2ID0gZGF0YS0+aGRldjsNCj4gQEAgLTEyMDUsOCAr
MTI2NiwxMCBAQCBkb25lOg0KPiAgDQo+ICAJcmV0dXJuIGVycjsNCj4gIH0NCj4gK0VYUE9SVF9T
WU1CT0xfR1BMKGJ0dXNiX3Jlc3VtZSk7DQo+ICAjZW5kaWYNCj4gIA0KPiArDQo+ICBzdGF0aWMg
c3RydWN0IHVzYl9kcml2ZXIgYnR1c2JfZHJpdmVyID0gew0KPiAgCS5uYW1lCQk9ICJidHVzYiIs
DQo+ICAJLnByb2JlCQk9IGJ0dXNiX3Byb2JlLA0KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ibHVl
dG9vdGgvYnR1c2IuaCBiL2RyaXZlcnMvYmx1ZXRvb3RoL2J0dXNiLmggbmV3IA0KPiBmaWxlIG1v
ZGUgMTAwNjQ0IGluZGV4IDAwMDAwMDAuLmMyNmE4NDUNCj4gLS0tIC9kZXYvbnVsbA0KPiArKysg
Yi9kcml2ZXJzL2JsdWV0b290aC9idHVzYi5oDQo+IEBAIC0wLDAgKzEsNTMgQEANCj4gKy8qDQo+
ICsgKg0KPiArICogIEdlbmVyaWMgQmx1ZXRvb3RoIFVTQiBkcml2ZXINCj4gKyAqDQo+ICsgKiAg
Q29weXJpZ2h0IChDKSAyMDA1LTIwMDggIE1hcmNlbCBIb2x0bWFubiA8bWFyY2VsQGhvbHRtYW5u
Lm9yZz4NCj4gKyAqDQo+ICsgKg0KPiArICogIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJl
OyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgDQo+ICttb2RpZnkNCj4gKyAqICBpdCB1
bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxp
c2hlZCANCj4gK2J5DQo+ICsgKiAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVy
IHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3INCj4gKyAqICAoYXQgeW91ciBvcHRpb24pIGFu
eSBsYXRlciB2ZXJzaW9uLg0KPiArICoNCj4gKyAqICBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0
ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwNCj4gKyAqICBidXQgV0lUSE9V
VCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZg0KPiAr
ICogIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4g
IFNlZSB0aGUNCj4gKyAqICBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRh
aWxzLg0KPiArICoNCj4gKyAqICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRo
ZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQ0KPiArICogIGFsb25nIHdpdGggdGhpcyBwcm9n
cmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlDQo+ICsgKiAgRm91bmRhdGlv
biwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIA0KPiArMDIx
MTEtMTMwNyAgVVNBDQo+ICsgKg0KPiArICovDQo+ICsjaWZuZGVmIF9CVFVTQl9IDQo+ICsjZGVm
aW5lIF9CVFVTQl9IDQo+ICsNCj4gK3N0cnVjdCBidHVzYl9kcml2ZXJfaW5mbyB7DQo+ICsJY2hh
cgkqZGVzY3JpcHRpb247DQo+ICsJaW50CWZsYWdzOw0KPiArI2RlZmluZSBCVFVTQl9HRU5FUklD
CQkweDAwDQo+ICsjZGVmaW5lIEJUVVNCX0lHTk9SRQkJMHgwMQ0KPiArI2RlZmluZSBCVFVTQl9E
SUdJQU5TV0VSCTB4MDINCj4gKyNkZWZpbmUgQlRVU0JfQ1NSCQkweDA0DQo+ICsjZGVmaW5lIEJU
VVNCX1NOSUZGRVIJCTB4MDgNCj4gKyNkZWZpbmUgQlRVU0JfQkNNOTIwMzUJCTB4MTANCj4gKyNk
ZWZpbmUgQlRVU0JfQlJPS0VOX0lTT0MJMHgyMA0KPiArI2RlZmluZSBCVFVTQl9XUk9OR19TQ09f
TVRVCTB4NDANCj4gKyNkZWZpbmUgQlRVU0JfQVRIMzAxMgkJMHg4MA0KPiArDQo+ICsJLyogZW50
cnkgcG9pbnQgZm9yIHZlbmRvciBzcGVjaWZpYyBkZXZpY2UgaW5pdGlhbGl6YXRpb24gKi8NCj4g
KwlpbnQJKCp2c2Rldl9pbml0KShzdHJ1Y3QgaGNpX2RldiAqaGRldik7DQoNCj4+IEtlZXAgaXQg
c2ltcGxlLiBDYWxsIHRoaXMgKCpzZXR1cCkuDQoNCj4gKw0KPiArCS8qIGV2ZW50IGhhbmRsZXIg
ZHVyaW5nIHZlbmRvciBzcGVjaWZpYyBkZXZpY2UgaW5pdGlhdGlvbiBwaGFzZSAqLw0KPiArCXZv
aWQJKCp2c2Rldl9ldmVudCkoc3RydWN0IGhjaV9kZXYgKmhkZXYsIHN0cnVjdCBza19idWZmICpz
a2IpOw0KDQo+PkFuZCB0aGlzIGp1c3QgKCpldmVudCkuDQoNCj4+IEkgYW0gc3RpbGwgY3VyaW91
cyBpZiB3ZSB3b3VsZCBuZWVkIHRoZSBldmVudCBwYXJ0IGF0IGFsbCB3aGVuIHVzaW5nIEhDSSBj
b21tYW5kIGhhbmRsaW5nIHdpdGggY2FsbGJhY2tzLCBidXQgSSBrbm93IGF0IGxlYXN0IHRoYXQg
Q1NSIGlzIG5vdCBmb2xsb3dpbmcgdGhlIEhDSSBzcGVjaWZpY2F0aW9uIGZvciBjb21tYW5kICsg
ZXZlbnQsIHNvIGl0IG1pZ2h0IGJlIGEgZ29vZCBpZGVhLg0KDQo+ICt9Ow0KPiArDQo+ICtleHRl
cm4gaW50IGJ0dXNiX3Byb2JlKHN0cnVjdCB1c2JfaW50ZXJmYWNlICosIGNvbnN0IHN0cnVjdCAN
Cj4gK3VzYl9kZXZpY2VfaWQgKik7IGV4dGVybiB2b2lkIGJ0dXNiX2Rpc2Nvbm5lY3Qoc3RydWN0
IHVzYl9pbnRlcmZhY2UgDQo+ICsqKTsgI2lmZGVmIENPTkZJR19QTSBleHRlcm4gaW50IGJ0dXNi
X3N1c3BlbmQoc3RydWN0IHVzYl9pbnRlcmZhY2UgKiwgDQo+ICtwbV9tZXNzYWdlX3QpOyBleHRl
cm4gaW50IGJ0dXNiX3Jlc3VtZShzdHJ1Y3QgdXNiX2ludGVyZmFjZSAqKTsgDQo+ICsjZW5kaWYN
Cj4gKw0KPiArI2VuZGlmIC8qIF9CVFVTQl9IICovDQo+IGRpZmYgLS1naXQgYS9pbmNsdWRlL25l
dC9ibHVldG9vdGgvaGNpX2NvcmUuaCANCj4gYi9pbmNsdWRlL25ldC9ibHVldG9vdGgvaGNpX2Nv
cmUuaA0KPiBpbmRleCA2YTMzMzdlLi40YWY2MDFkIDEwMDY0NA0KPiAtLS0gYS9pbmNsdWRlL25l
dC9ibHVldG9vdGgvaGNpX2NvcmUuaA0KPiArKysgYi9pbmNsdWRlL25ldC9ibHVldG9vdGgvaGNp
X2NvcmUuaA0KPiBAQCAtMjc1LDYgKzI3NSwxNiBAQCBzdHJ1Y3QgaGNpX2RldiB7DQo+ICAJaW50
ICgqc2VuZCkoc3RydWN0IHNrX2J1ZmYgKnNrYik7DQo+ICAJdm9pZCAoKm5vdGlmeSkoc3RydWN0
IGhjaV9kZXYgKmhkZXYsIHVuc2lnbmVkIGludCBldnQpOw0KPiAgCWludCAoKmlvY3RsKShzdHJ1
Y3QgaGNpX2RldiAqaGRldiwgdW5zaWduZWQgaW50IGNtZCwgdW5zaWduZWQgbG9uZyANCj4gYXJn
KTsNCj4gKw0KPiArCS8qDQo+ICsJICogVE9ETzogQWRkZWQgZm9sbG93aW5nIG1lbWJlcnMgZm9y
IHZlbmRvciBzcGVjaWZpYyBpbml0aWFsaXphdGlvbiB0bw0KPiArCSAqIG1ha2UgdGhlIGJsdWV0
b290aC5rbyB0cmFuc3BhcmVudCB0byB0aGUgaW50ZXJmYWNlLg0KPiArCSAqIFRoZXNlIG1lbWJl
cnMgYXJlIHNldCBieSB0aGUgdmVuZG9yIHByb3ZpZGVkIGRyaXZlcg0KPiArCSAqLw0KPiArCWlu
dAkJCXZzZGV2X2luaXRfZG9uZTsNCg0KPj4gRm9yIHRoaXMsIHBsZWFzZSB1c2UgZGV2X2ZsYWdz
LiBObyBuZWVkIHdhc3RlIHNwYWNlIHdpdGggYW5vdGhlciB2YXJpYWJsZS4NCg0KPiArCXZvaWQJ
CQkqdnNkZXZfcHJpdl9kYXRhOw0KPiArCWludCAoKnZzZGV2X2luaXQpKHN0cnVjdCBoY2lfZGV2
ICpoZGV2KTsNCj4gKwl2b2lkICgqdnNkZXZfZXZlbnQpKHN0cnVjdCBoY2lfZGV2ICpoZGV2LCBz
dHJ1Y3Qgc2tfYnVmZiAqc2tiKTsNCj4gIH07DQoNCj4+IFJhdGhlciBsaWtlIHZlbmRvcl9zZXR1
cCBhbmQgdmVuZG9yX2V2ZW50IGhlcmUuIEkgZG8gbm90IGV2ZW4gd2FudCB0byBrbm93IHdoYXQg
dnMgc3RhbmRzIGZvciA7KQ0KDQo+PiBIb3BlIHdlIGFyZSBub3QgZ2V0dGluZyBpbnRvIHRyb3Vi
bGUgd2l0aCBkcml2ZXIgaWQgdGFibGVzIG5vcm1hbGx5IGJlaW5nIGNvbnN0Lg0KDQo+ICANCj4g
IHN0cnVjdCBoY2lfY29ubiB7DQo+IGRpZmYgLS1naXQgYS9uZXQvYmx1ZXRvb3RoL2hjaV9jb3Jl
LmMgYi9uZXQvYmx1ZXRvb3RoL2hjaV9jb3JlLmMgaW5kZXggDQo+IGU0MDcwNTEuLjgwYWExM2Yg
MTAwNjQ0DQo+IC0tLSBhL25ldC9ibHVldG9vdGgvaGNpX2NvcmUuYw0KPiArKysgYi9uZXQvYmx1
ZXRvb3RoL2hjaV9jb3JlLmMNCj4gQEAgLTY4NSw2ICs2ODUsMTUgQEAgaW50IGhjaV9kZXZfb3Bl
bihfX3UxNiBkZXYpDQo+ICAJCXNldF9iaXQoSENJX0lOSVQsICZoZGV2LT5mbGFncyk7DQo+ICAJ
CWhkZXYtPmluaXRfbGFzdF9jbWQgPSAwOw0KPiAgDQo+ICsJCS8qIHZlbmRvciBzcGVjaWZpYyBk
ZXZpY2UgaW5pdGlhbGl6YXRpb24gKi8NCj4gKwkJaWYgKGhkZXYtPnZzZGV2X2luaXQpIHsNCj4g
KwkJCXJldCA9IGhkZXYtPnZzZGV2X2luaXQoaGRldik7DQo+ICsJCQloZGV2LT52c2Rldl9pbml0
X2RvbmUgPSAxOw0KPiArCQkJaGRldi0+dnNkZXZfZXZlbnQgPSBOVUxMOw0KPiArCQkJaWYgKHJl
dCA8IDApDQo+ICsJCQkJZ290byBkb25lOw0KPiArCQl9DQo+ICsNCg0KPj4gRG8geW91IHJlYWxs
eSB3YW50IHRvIGRvIHRoaXMgb24gZXZlcnkgaGNpY29uZmlnIGhjaTAgdXA/IEkgYXNzdW1lZCB0
aGlzIGlzIGEgb25lIHRpbWUgdGFzay4gU28geW91IG1pZ2h0IGJldHRlciBsb29rIGF0IGhjaV9w
b3dlcl9vbigpIGZvciB0aGlzLg0KDQo+PiBJcyBhIEhDSV9SZXNldCBjb21tYW5kIHVubG9hZGlu
ZyB0aGUgZmlybXdhcmUgcGF0Y2hlcy4NCg0KPiAgCQlyZXQgPSBfX2hjaV9yZXF1ZXN0KGhkZXYs
IGhjaV9pbml0X3JlcSwgMCwgSENJX0lOSVRfVElNRU9VVCk7DQo+ICANCj4gIAkJaWYgKGxtcF9o
b3N0X2xlX2NhcGFibGUoaGRldikpDQo+IEBAIC0yMTE5LDYgKzIxMjgsNyBAQCBpbnQgaGNpX3Nl
bmRfY21kKHN0cnVjdCBoY2lfZGV2ICpoZGV2LCBfX3UxNiANCj4gb3Bjb2RlLCBfX3UzMiBwbGVu
LCB2b2lkICpwYXJhbSkNCj4gIA0KPiAgCXJldHVybiAwOw0KPiAgfQ0KPiArRVhQT1JUX1NZTUJP
TChoY2lfc2VuZF9jbWQpOw0KPiAgDQo+ICAvKiBHZXQgZGF0YSBmcm9tIHRoZSBwcmV2aW91c2x5
IHNlbnQgY29tbWFuZCAqLyAgdm9pZCANCj4gKmhjaV9zZW50X2NtZF9kYXRhKHN0cnVjdCBoY2lf
ZGV2ICpoZGV2LCBfX3UxNiBvcGNvZGUpIEBAIC0yODAwLDcgDQo+ICsyODEwLDEwIEBAIHN0YXRp
YyB2b2lkIGhjaV9yeF93b3JrKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykNCj4gIAkJc3dpdGNo
IChidF9jYihza2IpLT5wa3RfdHlwZSkgew0KPiAgCQljYXNlIEhDSV9FVkVOVF9QS1Q6DQo+ICAJ
CQlCVF9EQkcoIiVzIEV2ZW50IHBhY2tldCIsIGhkZXYtPm5hbWUpOw0KPiAtCQkJaGNpX2V2ZW50
X3BhY2tldChoZGV2LCBza2IpOw0KPiArCQkJaWYgKGhkZXYtPnZzZGV2X2V2ZW50ICYmICFoZGV2
LT52c2Rldl9pbml0X2RvbmUpDQo+ICsJCQkJaGRldi0+dnNkZXZfZXZlbnQoaGRldiwgc2tiKTsN
Cj4gKwkJCWVsc2UNCj4gKwkJCQloY2lfZXZlbnRfcGFja2V0KGhkZXYsIHNrYik7DQo+ICAJCQli
cmVhazsNCg0KPj4gTm90IGdvaW5nIHRocm91Z2ggaGNpX2V2ZW50X3BhY2tldCBpcyBhIGJhZCBp
ZGVhLiBUaGF0IHdpbGwgc2NyZXcgb3ZlciB0aGUgZmxvdyBjb250cm9sIGhhbmRsaW5nIGZvciBj
b21tYW5kcy4NCg0KPj4gUmVnYXJkcw0KDQo+PiBNYXJjZWwNCg0KUmVnYXJkcywNCkFsYmVydA0K
DQoNCg0K

2012-10-04 10:20:13

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC 1/2] Bluetooth: Add driver extension for vendor specific init

Hi Tedd,

> This patch provides an extension of btusb to support device vendor
> can implement their own module to execute the vendor specific
> device initialization before the stack sends generic BT device
> initialization.
>
> Signed-off-by: Tedd Ho-Jeong An <[email protected]>
> ---
> drivers/bluetooth/btusb.c | 191 +++++++++++++++++++++++++-------------
> drivers/bluetooth/btusb.h | 53 +++++++++++
> include/net/bluetooth/hci_core.h | 10 ++
> net/bluetooth/hci_core.c | 15 ++-
> 4 files changed, 204 insertions(+), 65 deletions(-)
> create mode 100644 drivers/bluetooth/btusb.h
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index f637c25..afa1558 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -26,6 +26,7 @@
>
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
> +#include "btusb.h"
>
> #define VERSION "0.6"
>
> @@ -39,14 +40,59 @@ static bool reset = 1;
>
> static struct usb_driver btusb_driver;
>
> -#define BTUSB_IGNORE 0x01
> -#define BTUSB_DIGIANSWER 0x02
> -#define BTUSB_CSR 0x04
> -#define BTUSB_SNIFFER 0x08
> -#define BTUSB_BCM92035 0x10
> -#define BTUSB_BROKEN_ISOC 0x20
> -#define BTUSB_WRONG_SCO_MTU 0x40
> -#define BTUSB_ATH3012 0x80
> +/*
> + * Create btusb_driver_info struct for each driver_info flags used by
> + * blacklist since vendor's btusb driver will return btusb_driver_info struct.
> + */
> +
> +/*
> + * if the device is set to this, this menas that the device is generic and
> + * doesn't require any vendor specific handling
> + */
> +static const struct btusb_driver_info generic = {
> + .description = "BTUSB Generic",
> + .flags = BTUSB_GENERIC,
> +};
> +
> +static const struct btusb_driver_info ignore = {
> + .description = "BTUSB Ignore",
> + .flags = BTUSB_IGNORE,
> +};

I like the effort, but I think you went a little bit too far here. For
these simple ones, we can easily keep our simple blacklist. It keeps the
code more readable than this part. But I do appreciate the attempt in
unifying this.

> +
> +static const struct btusb_driver_info digianswer = {
> + .description = "BTUSB DIGIANSWER",
> + .flags = BTUSB_DIGIANSWER,
> +};
> +
> +static const struct btusb_driver_info csr = {
> + .description = "BTUSB CSR",
> + .flags = BTUSB_CSR,
> +};
> +
> +static const struct btusb_driver_info sniffer = {
> + .description = "BTUSB Sniffer",
> + .flags = BTUSB_SNIFFER,
> +};
> +
> +static const struct btusb_driver_info bcm92035 = {
> + .description = "BTUSB BCM92035",
> + .flags = BTUSB_BCM92035,
> +};
> +
> +static const struct btusb_driver_info broken_isoc = {
> + .description = "BTUSB Broken ISOC",
> + .flags = BTUSB_BROKEN_ISOC,
> +};
> +
> +static const struct btusb_driver_info wrong_sco_mtu = {
> + .description = "BTUSB Wrong SCO MTU",
> + .flags = BTUSB_WRONG_SCO_MTU,
> +};
> +
> +static const struct btusb_driver_info ath3012 = {
> + .description = "BTUSB Ath3012",
> + .flags = BTUSB_ATH3012,
> +};
>
> static struct usb_device_id btusb_table[] = {
> /* Generic Bluetooth USB device */
> @@ -105,90 +151,89 @@ static struct usb_device_id btusb_table[] = {
>
> { } /* Terminating entry */
> };
> -
> MODULE_DEVICE_TABLE(usb, btusb_table);
>
> static struct usb_device_id blacklist_table[] = {
> /* CSR BlueCore devices */
> - { USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
> + { USB_DEVICE(0x0a12, 0x0001), .driver_info = (unsigned long) &csr },

Keep the blacklist_table as it is. The important table to modify is
btusb_table and use a common driver_info that will be shared between
drivers.

That would also make it simple to just add BTUSB_IGNORE or a new
BTUSB_VENDOR flag to call out the drivers that have a separate driver
with a vendor init function, but would match the Bluetooth general USB
descriptors.

Then over time, we can move the BTUSB_BCM92035 for example into its
separate driver. And also deal with cleaning up all the other Broadcom
specialties.

>
> /* Broadcom BCM2033 without firmware */
> - { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
> + { USB_DEVICE(0x0a5c, 0x2033), .driver_info = (unsigned long) &ignore },
>
> /* Atheros 3011 with sflash firmware */
> - { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
> - { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
> - { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
> - { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
> - { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
> + { USB_DEVICE(0x0cf3, 0x3002), .driver_info = (unsigned long) &ignore },
> + { USB_DEVICE(0x0cf3, 0xe019), .driver_info = (unsigned long) &ignore },
> + { USB_DEVICE(0x13d3, 0x3304), .driver_info = (unsigned long) &ignore },
> + { USB_DEVICE(0x0930, 0x0215), .driver_info = (unsigned long) &ignore },
> + { USB_DEVICE(0x0489, 0xe03d), .driver_info = (unsigned long) &ignore },
>
> /* Atheros AR9285 Malbec with sflash firmware */
> - { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
> + { USB_DEVICE(0x03f0, 0x311d), .driver_info = (unsigned long) &ignore },
>
> /* Atheros 3012 with sflash firmware */
> - { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
> - { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
> - { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
> - { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
> - { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
> - { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
> - { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
> + { USB_DEVICE(0x0cf3, 0x3004), .driver_info = (unsigned long) &ath3012 },
> + { USB_DEVICE(0x0cf3, 0x311d), .driver_info = (unsigned long) &ath3012 },
> + { USB_DEVICE(0x13d3, 0x3375), .driver_info = (unsigned long) &ath3012 },
> + { USB_DEVICE(0x04ca, 0x3005), .driver_info = (unsigned long) &ath3012 },
> + { USB_DEVICE(0x13d3, 0x3362), .driver_info = (unsigned long) &ath3012 },
> + { USB_DEVICE(0x0cf3, 0xe004), .driver_info = (unsigned long) &ath3012 },
> + { USB_DEVICE(0x0930, 0x0219), .driver_info = (unsigned long) &ath3012 },
>
> /* Atheros AR5BBU12 with sflash firmware */
> - { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
> + { USB_DEVICE(0x0489, 0xe02c), .driver_info = (unsigned long) &ignore },
>
> /* Atheros AR5BBU12 with sflash firmware */
> - { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
> + { USB_DEVICE(0x0489, 0xe03c), .driver_info = (unsigned long) &ath3012 },
>
> /* Broadcom BCM2035 */
> - { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
> - { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
> - { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
> + { USB_DEVICE(0x0a5c, 0x2035), .driver_info = (unsigned long) &wrong_sco_mtu },
> + { USB_DEVICE(0x0a5c, 0x200a), .driver_info = (unsigned long) &wrong_sco_mtu },
> + { USB_DEVICE(0x0a5c, 0x2009), .driver_info = (unsigned long) &bcm92035 },
>
> /* Broadcom BCM2045 */
> - { USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
> - { USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_WRONG_SCO_MTU },
> + { USB_DEVICE(0x0a5c, 0x2039), .driver_info = (unsigned long) &wrong_sco_mtu },
> + { USB_DEVICE(0x0a5c, 0x2101), .driver_info = (unsigned long) &wrong_sco_mtu },
>
> /* IBM/Lenovo ThinkPad with Broadcom chip */
> - { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_WRONG_SCO_MTU },
> - { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_WRONG_SCO_MTU },
> + { USB_DEVICE(0x0a5c, 0x201e), .driver_info = (unsigned long) &wrong_sco_mtu },
> + { USB_DEVICE(0x0a5c, 0x2110), .driver_info = (unsigned long) &wrong_sco_mtu },
>
> /* HP laptop with Broadcom chip */
> - { USB_DEVICE(0x03f0, 0x171d), .driver_info = BTUSB_WRONG_SCO_MTU },
> + { USB_DEVICE(0x03f0, 0x171d), .driver_info = (unsigned long) &wrong_sco_mtu },
>
> /* Dell laptop with Broadcom chip */
> - { USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_WRONG_SCO_MTU },
> + { USB_DEVICE(0x413c, 0x8126), .driver_info = (unsigned long) &wrong_sco_mtu },
>
> /* Dell Wireless 370 and 410 devices */
> - { USB_DEVICE(0x413c, 0x8152), .driver_info = BTUSB_WRONG_SCO_MTU },
> - { USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_WRONG_SCO_MTU },
> + { USB_DEVICE(0x413c, 0x8152), .driver_info = (unsigned long) &wrong_sco_mtu },
> + { USB_DEVICE(0x413c, 0x8156), .driver_info = (unsigned long) &wrong_sco_mtu },
>
> /* Belkin F8T012 and F8T013 devices */
> - { USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_WRONG_SCO_MTU },
> - { USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_WRONG_SCO_MTU },
> + { USB_DEVICE(0x050d, 0x0012), .driver_info = (unsigned long) &wrong_sco_mtu },
> + { USB_DEVICE(0x050d, 0x0013), .driver_info = (unsigned long) &wrong_sco_mtu },
>
> /* Asus WL-BTD202 device */
> - { USB_DEVICE(0x0b05, 0x1715), .driver_info = BTUSB_WRONG_SCO_MTU },
> + { USB_DEVICE(0x0b05, 0x1715), .driver_info = (unsigned long) &wrong_sco_mtu },
>
> /* Kensington Bluetooth USB adapter */
> - { USB_DEVICE(0x047d, 0x105e), .driver_info = BTUSB_WRONG_SCO_MTU },
> + { USB_DEVICE(0x047d, 0x105e), .driver_info = (unsigned long) &wrong_sco_mtu },
>
> /* RTX Telecom based adapters with buggy SCO support */
> - { USB_DEVICE(0x0400, 0x0807), .driver_info = BTUSB_BROKEN_ISOC },
> - { USB_DEVICE(0x0400, 0x080a), .driver_info = BTUSB_BROKEN_ISOC },
> + { USB_DEVICE(0x0400, 0x0807), .driver_info = (unsigned long) &broken_isoc },
> + { USB_DEVICE(0x0400, 0x080a), .driver_info = (unsigned long) &broken_isoc },
>
> /* CONWISE Technology based adapters with buggy SCO support */
> - { USB_DEVICE(0x0e5e, 0x6622), .driver_info = BTUSB_BROKEN_ISOC },
> + { USB_DEVICE(0x0e5e, 0x6622), .driver_info = (unsigned long) &broken_isoc },
>
> /* Digianswer devices */
> - { USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
> - { USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
> + { USB_DEVICE(0x08fd, 0x0001), .driver_info = (unsigned long) &digianswer },
> + { USB_DEVICE(0x08fd, 0x0002), .driver_info = (unsigned long) &ignore },
>
> /* CSR BlueCore Bluetooth Sniffer */
> - { USB_DEVICE(0x0a12, 0x0002), .driver_info = BTUSB_SNIFFER },
> + { USB_DEVICE(0x0a12, 0x0002), .driver_info = (unsigned long) &sniffer },
>
> /* Frontline ComProbe Bluetooth Sniffer */
> - { USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER },
> + { USB_DEVICE(0x16d3, 0x0002), .driver_info = (unsigned long) &sniffer },
>
> { } /* Terminating entry */
> };
> @@ -910,12 +955,12 @@ static void btusb_waker(struct work_struct *work)
> usb_autopm_put_interface(data->intf);
> }
>
> -static int btusb_probe(struct usb_interface *intf,
> - const struct usb_device_id *id)
> +int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
> {
> struct usb_endpoint_descriptor *ep_desc;
> struct btusb_data *data;
> struct hci_dev *hdev;
> + struct btusb_driver_info *info;
> int i, err;
>
> BT_DBG("intf %p id %p", intf, id);
> @@ -931,19 +976,28 @@ static int btusb_probe(struct usb_interface *intf,
> id = match;
> }
>
> - if (id->driver_info == BTUSB_IGNORE)
> + /*
> + * Make sure the driver_info is not null or 0 because the code below
> + * need to access the flags
> + */
> + if (!id->driver_info)
> + info = (struct btusb_driver_info *) &generic;
> + else
> + info = (struct btusb_driver_info *) id->driver_info;
> +
> + if (info->flags == BTUSB_IGNORE)
> return -ENODEV;
>
> - if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
> + if (ignore_dga && (info->flags & BTUSB_DIGIANSWER))
> return -ENODEV;
>
> - if (ignore_csr && id->driver_info & BTUSB_CSR)
> + if (ignore_csr && (info->flags & BTUSB_CSR))
> return -ENODEV;
>
> - if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
> + if (ignore_sniffer && (info->flags & BTUSB_SNIFFER))
> return -ENODEV;
>
> - if (id->driver_info & BTUSB_ATH3012) {
> + if (info->flags & BTUSB_ATH3012) {
> struct usb_device *udev = interface_to_usbdev(intf);
>
> /* Old firmware would otherwise let ath3k driver load
> @@ -1012,26 +1066,30 @@ static int btusb_probe(struct usb_interface *intf,
> hdev->send = btusb_send_frame;
> hdev->notify = btusb_notify;
>
> + /* vendor specific device initialization routines */
> + hdev->vsdev_init = info->vsdev_init;
> + hdev->vsdev_event = info->vsdev_event;
> +
> /* Interface numbers are hardcoded in the specification */
> data->isoc = usb_ifnum_to_if(data->udev, 1);
>
> if (!reset)
> set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
>
> - if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
> + if (force_scofix || (info->flags & BTUSB_WRONG_SCO_MTU)) {
> if (!disable_scofix)
> set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
> }
>
> - if (id->driver_info & BTUSB_BROKEN_ISOC)
> + if (info->flags & BTUSB_BROKEN_ISOC)
> data->isoc = NULL;
>
> - if (id->driver_info & BTUSB_DIGIANSWER) {
> + if (info->flags & BTUSB_DIGIANSWER) {
> data->cmdreq_type = USB_TYPE_VENDOR;
> set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
> }
>
> - if (id->driver_info & BTUSB_CSR) {
> + if (info->flags & BTUSB_CSR) {
> struct usb_device *udev = data->udev;
>
> /* Old firmware would otherwise execute USB reset */
> @@ -1039,7 +1097,7 @@ static int btusb_probe(struct usb_interface *intf,
> set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
> }
>
> - if (id->driver_info & BTUSB_SNIFFER) {
> + if (info->flags & BTUSB_SNIFFER) {
> struct usb_device *udev = data->udev;
>
> /* New sniffer firmware has crippled HCI interface */
> @@ -1049,7 +1107,7 @@ static int btusb_probe(struct usb_interface *intf,
> data->isoc = NULL;
> }
>
> - if (id->driver_info & BTUSB_BCM92035) {
> + if (info->flags & BTUSB_BCM92035) {
> unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
> struct sk_buff *skb;
>
> @@ -1079,8 +1137,9 @@ static int btusb_probe(struct usb_interface *intf,
>
> return 0;
> }
> +EXPORT_SYMBOL_GPL(btusb_probe);
>
> -static void btusb_disconnect(struct usb_interface *intf)
> +void btusb_disconnect(struct usb_interface *intf)
> {
> struct btusb_data *data = usb_get_intfdata(intf);
> struct hci_dev *hdev;
> @@ -1105,9 +1164,10 @@ static void btusb_disconnect(struct usb_interface *intf)
>
> hci_free_dev(hdev);
> }
> +EXPORT_SYMBOL_GPL(btusb_disconnect);
>
> #ifdef CONFIG_PM
> -static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
> +int btusb_suspend(struct usb_interface *intf, pm_message_t message)
> {
> struct btusb_data *data = usb_get_intfdata(intf);
>
> @@ -1133,6 +1193,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
>
> return 0;
> }
> +EXPORT_SYMBOL_GPL(btusb_suspend);
>
> static void play_deferred(struct btusb_data *data)
> {
> @@ -1149,7 +1210,7 @@ static void play_deferred(struct btusb_data *data)
> usb_scuttle_anchored_urbs(&data->deferred);
> }
>
> -static int btusb_resume(struct usb_interface *intf)
> +int btusb_resume(struct usb_interface *intf)
> {
> struct btusb_data *data = usb_get_intfdata(intf);
> struct hci_dev *hdev = data->hdev;
> @@ -1205,8 +1266,10 @@ done:
>
> return err;
> }
> +EXPORT_SYMBOL_GPL(btusb_resume);
> #endif
>
> +
> static struct usb_driver btusb_driver = {
> .name = "btusb",
> .probe = btusb_probe,
> diff --git a/drivers/bluetooth/btusb.h b/drivers/bluetooth/btusb.h
> new file mode 100644
> index 0000000..c26a845
> --- /dev/null
> +++ b/drivers/bluetooth/btusb.h
> @@ -0,0 +1,53 @@
> +/*
> + *
> + * Generic Bluetooth USB driver
> + *
> + * Copyright (C) 2005-2008 Marcel Holtmann <[email protected]>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + */
> +#ifndef _BTUSB_H
> +#define _BTUSB_H
> +
> +struct btusb_driver_info {
> + char *description;
> + int flags;
> +#define BTUSB_GENERIC 0x00
> +#define BTUSB_IGNORE 0x01
> +#define BTUSB_DIGIANSWER 0x02
> +#define BTUSB_CSR 0x04
> +#define BTUSB_SNIFFER 0x08
> +#define BTUSB_BCM92035 0x10
> +#define BTUSB_BROKEN_ISOC 0x20
> +#define BTUSB_WRONG_SCO_MTU 0x40
> +#define BTUSB_ATH3012 0x80
> +
> + /* entry point for vendor specific device initialization */
> + int (*vsdev_init)(struct hci_dev *hdev);

Keep it simple. Call this (*setup).
> +
> + /* event handler during vendor specific device initiation phase */
> + void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);

And this just (*event).

I am still curious if we would need the event part at all when using HCI
command handling with callbacks, but I know at least that CSR is not
following the HCI specification for command + event, so it might be a
good idea.

> +};
> +
> +extern int btusb_probe(struct usb_interface *, const struct usb_device_id *);
> +extern void btusb_disconnect(struct usb_interface *);
> +#ifdef CONFIG_PM
> +extern int btusb_suspend(struct usb_interface *, pm_message_t);
> +extern int btusb_resume(struct usb_interface *);
> +#endif
> +
> +#endif /* _BTUSB_H */
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 6a3337e..4af601d 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -275,6 +275,16 @@ struct hci_dev {
> int (*send)(struct sk_buff *skb);
> void (*notify)(struct hci_dev *hdev, unsigned int evt);
> int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
> +
> + /*
> + * TODO: Added following members for vendor specific initialization to
> + * make the bluetooth.ko transparent to the interface.
> + * These members are set by the vendor provided driver
> + */
> + int vsdev_init_done;

For this, please use dev_flags. No need waste space with another
variable.

> + void *vsdev_priv_data;
> + int (*vsdev_init)(struct hci_dev *hdev);
> + void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);
> };

Rather like vendor_setup and vendor_event here. I do not even want to
know what vs stands for ;)

Hope we are not getting into trouble with driver id tables normally
being const.

>
> struct hci_conn {
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index e407051..80aa13f 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -685,6 +685,15 @@ int hci_dev_open(__u16 dev)
> set_bit(HCI_INIT, &hdev->flags);
> hdev->init_last_cmd = 0;
>
> + /* vendor specific device initialization */
> + if (hdev->vsdev_init) {
> + ret = hdev->vsdev_init(hdev);
> + hdev->vsdev_init_done = 1;
> + hdev->vsdev_event = NULL;
> + if (ret < 0)
> + goto done;
> + }
> +

Do you really want to do this on every hciconfig hci0 up? I assumed this
is a one time task. So you might better look at hci_power_on() for this.

Is a HCI_Reset command unloading the firmware patches.

> ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
>
> if (lmp_host_le_capable(hdev))
> @@ -2119,6 +2128,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
>
> return 0;
> }
> +EXPORT_SYMBOL(hci_send_cmd);
>
> /* Get data from the previously sent command */
> void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
> @@ -2800,7 +2810,10 @@ static void hci_rx_work(struct work_struct *work)
> switch (bt_cb(skb)->pkt_type) {
> case HCI_EVENT_PKT:
> BT_DBG("%s Event packet", hdev->name);
> - hci_event_packet(hdev, skb);
> + if (hdev->vsdev_event && !hdev->vsdev_init_done)
> + hdev->vsdev_event(hdev, skb);
> + else
> + hci_event_packet(hdev, skb);
> break;

Not going through hci_event_packet is a bad idea. That will screw over
the flow control handling for commands.

Regards

Marcel