Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111372861
D44861.id137444.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D44861.id137444.diff
View Options
diff --git a/libexec/rc/rc.d/bluetooth b/libexec/rc/rc.d/bluetooth
--- a/libexec/rc/rc.d/bluetooth
+++ b/libexec/rc/rc.d/bluetooth
@@ -127,8 +127,17 @@
> /dev/null 2>&1 || return 1
# Initilalize HCI node
- ${hccontrol} -n ${dev}hci reset \
- > /dev/null 2>&1 || return 1
+ for loop in 1 2 3
+ do
+ ${hccontrol} -n ${dev}hci reset \
+ > /dev/null 2>1 && break
+ if [ ${loop} = 3 ]
+ then
+ warn Reset failed three times, giving up.
+ return 1
+ fi
+ warn Reset failed, retrying.
+ done
${hccontrol} -n ${dev}hci read_bd_addr \
> /dev/null 2>&1 || return 1
diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c
--- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c
+++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c
@@ -59,6 +59,7 @@
enum {
UBT_INTEL_DEVICE_7260,
UBT_INTEL_DEVICE_8260,
+ UBT_INTEL_DEVICE_TLV,
};
struct ubt_intel_version_rp {
@@ -74,6 +75,11 @@
uint8_t fw_patch_num;
} __attribute__ ((packed));
+struct ubt_intel_tlv_field {
+ uint8_t type;
+ uint8_t len;
+ uint8_t val[];
+} __attribute__ ((packed));
static device_probe_t ubt_intel_probe;
/*
@@ -93,6 +99,8 @@
{ USB_VPI(USB_VENDOR_INTEL2, 0x0025, UBT_INTEL_DEVICE_8260) },
{ USB_VPI(USB_VENDOR_INTEL2, 0x0026, UBT_INTEL_DEVICE_8260) },
{ USB_VPI(USB_VENDOR_INTEL2, 0x0029, UBT_INTEL_DEVICE_8260) },
+ /* Intel AX210 */
+ { USB_VPI(USB_VENDOR_INTEL2, 0x0032, UBT_INTEL_DEVICE_TLV) },
};
/*
@@ -128,6 +136,50 @@
return (error);
}
+static bool
+ubt_intel_tlv_is_firmware_running(struct usb_device *dev)
+{
+#define TLV_BUFFER_SIZE 252
+ uint8_t evtbuf[offsetof(struct ubt_hci_event_command_compl, data) + TLV_BUFFER_SIZE] = {0};
+ struct ubt_hci_event_command_compl *evt = (struct ubt_hci_event_command_compl *)evtbuf;
+ uint8_t cmdbuf[offsetof(struct ubt_hci_cmd, data) + 1];
+ struct ubt_hci_cmd *cmd = (struct ubt_hci_cmd *)cmdbuf;
+ usb_error_t error;
+ struct ubt_intel_tlv_field *f;
+ size_t pos;
+
+ cmd->opcode = htole16(0xfc05),
+ cmd->length = 1,
+ cmd->data[0] = 0xff;
+
+ evt->header.length = TLV_BUFFER_SIZE + UBT_HCI_EVENT_COMPL_HEAD_SIZE;
+
+ error = ubt_do_hci_request(dev, cmd, evt, UBT_INTEL_HCICMD_TIMEOUT);
+ if (error != USB_ERR_NORMAL_COMPLETION)
+ return false;
+
+ if (evt->header.event != NG_HCI_EVENT_COMMAND_COMPL)
+ return false;
+
+ pos = offsetof(struct ubt_hci_event_command_compl, data);
+
+ while ((pos + 2) < evt->header.length) {
+ f = (struct ubt_intel_tlv_field *) &evt->data[pos];
+ if (pos + f->len >= evt->header.length)
+ break;
+
+ if (f->type == 0x1c && f->len == 1) {
+ if (f->val[0] == 0x03)
+ return true;
+ return false;
+ }
+
+ pos += offsetof(struct ubt_intel_tlv_field, val);
+ pos += f->len;
+ }
+ return false;
+}
+
/*
* Probe for a Intel Wireless Bluetooth device.
*/
@@ -193,6 +245,14 @@
return (ENXIO);
break;
+ case UBT_INTEL_DEVICE_TLV:
+ /*
+ * Find if the device is in bootloader mode or is running
+ * operational firmware.
+ */
+ if (!ubt_intel_tlv_is_firmware_running(uaa->device))
+ return ENXIO;
+ break;
default:
KASSERT(0 == 1, ("Unknown DRIVER_INFO"));
}
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h
@@ -42,6 +42,37 @@
uint8_t fw_patch_num;
} __attribute__ ((packed));
+struct iwmbt_tlv {
+ uint8_t status;
+#define IWMBT_TLV_MAX 4096
+ uint8_t tlv_data[IWMBT_TLV_MAX];
+ /* Must be at end (not part of transferred data) */
+ uint16_t tlv_len;
+} __attribute__ ((packed));
+
+struct iwmbt_tlv_field {
+ uint8_t type;
+ uint8_t len;
+ uint8_t val[];
+} __attribute__ ((packed));
+
+enum types {
+ IWMBT_TLV_TYPE_FNAME_FIRST = 0x10,
+ IWMBT_TLV_TYPE_FNAME_SECOND = 0x11,
+ IWMBT_TLV_TYPE_HW_VERSION = 0x12,
+ IWMBT_TLV_TYPE_RUNNING = 0x1e,
+ IWMBT_TLV_TYPE_SIGTYPE = 0x2f,
+};
+
+struct iwmbt_parsed_tlv {
+ uint32_t parse_state;
+ uint32_t fn_first;
+ uint32_t fn_second;
+ uint32_t hw_version;
+ uint8_t running;
+ uint8_t sigtype;
+};
+
struct iwmbt_boot_params {
uint8_t status;
uint8_t otp_format;
@@ -73,5 +104,8 @@
extern char *iwmbt_get_fwname(struct iwmbt_version *ver,
struct iwmbt_boot_params *params, const char *prefix,
const char *suffix);
+extern char *iwmbt_get_fwname_tlv(const char *prefix,
+ struct iwmbt_parsed_tlv *ptlv,
+ const char *suffix);
#endif
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
@@ -170,3 +170,23 @@
return (fwname);
}
+
+static uint16_t
+iwmbt_mangle_tlv_value(uint32_t val)
+{
+ uint16_t ret = ((val & 0xfff) << 4) | ((val & 0x0f000000) >> 24);
+ return bswap16(ret);
+}
+
+char *
+iwmbt_get_fwname_tlv(const char *prefix, struct iwmbt_parsed_tlv *ptlv, const char *suffix)
+{
+ char *fwname;
+
+ asprintf(&fwname, "%s/ibt-%04x-%04x.%s",
+ prefix,
+ iwmbt_mangle_tlv_value(ptlv->fn_first),
+ iwmbt_mangle_tlv_value(ptlv->fn_second),
+ suffix);
+ return fwname;
+}
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
@@ -27,6 +27,8 @@
#ifndef __IWMBT_HW_H__
#define __IWMBT_HW_H__
+#include <stdbool.h>
+
/* USB control request (HCI command) structure */
struct iwmbt_hci_cmd {
uint16_t opcode;
@@ -74,16 +76,18 @@
extern int iwmbt_patch_fwfile(struct libusb_device_handle *hdl,
const struct iwmbt_firmware *fw);
extern int iwmbt_load_fwfile(struct libusb_device_handle *hdl,
- const struct iwmbt_firmware *fw, uint32_t *boot_param);
+ const struct iwmbt_firmware *fw, uint32_t *boot_param, bool is_tlv, uint8_t sigtype);
extern int iwmbt_enter_manufacturer(struct libusb_device_handle *hdl);
extern int iwmbt_exit_manufacturer(struct libusb_device_handle *hdl,
int mode);
extern int iwmbt_get_version(struct libusb_device_handle *hdl,
struct iwmbt_version *version);
+extern int iwmbt_get_tlv(struct libusb_device_handle *hdl,
+ struct iwmbt_tlv *tlv);
extern int iwmbt_get_boot_params(struct libusb_device_handle *hdl,
struct iwmbt_boot_params *params);
extern int iwmbt_intel_reset(struct libusb_device_handle *hdl,
- uint32_t boot_param);
+ uint32_t boot_param, bool hard);
extern int iwmbt_load_ddc(struct libusb_device_handle *hdl,
const struct iwmbt_firmware *ddc);
extern int iwmbt_set_event_mask(struct libusb_device_handle *hdl);
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
@@ -269,7 +269,7 @@
int
iwmbt_load_fwfile(struct libusb_device_handle *hdl,
- const struct iwmbt_firmware *fw, uint32_t *boot_param)
+ const struct iwmbt_firmware *fw, uint32_t *boot_param, bool is_tlv, uint8_t sigtype)
{
int ready = 0, sent = 0;
int ret, transferred;
@@ -300,15 +300,26 @@
iwmbt_debug("file=%s, size=%d", fw->fwname, fw->len);
- IWMBT_SEND_FRAGMENT(0x00, 0x80, "CCS segment");
- IWMBT_SEND_FRAGMENT(0x03, 0x80, "public key / part 1");
- IWMBT_SEND_FRAGMENT(0x03, 0x80, "public key / part 2");
+ if (sigtype == 0 || !is_tlv) {
+ IWMBT_SEND_FRAGMENT(0x00, 0x80, "CCS segment");
+ IWMBT_SEND_FRAGMENT(0x03, 0x80, "public key / part 1");
+ IWMBT_SEND_FRAGMENT(0x03, 0x80, "public key / part 2");
- /* skip 4 bytes */
- sent += 4;
+ /* skip 4 bytes */
+ sent += 4;
- IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 1");
- IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 2");
+ IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 1");
+ IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 2");
+
+ if (is_tlv)
+ sent += 320;
+ } else {
+ sent += 644;
+
+ IWMBT_SEND_FRAGMENT(0x00, 128, "CSS segment");
+ IWMBT_SEND_FRAGMENT(0x03, 96, "public key?");
+ IWMBT_SEND_FRAGMENT(0x02, 96, "signature?");
+ }
/*
* Send firmware chunks. Chunk len must be 4 byte aligned.
@@ -460,6 +471,46 @@
return (0);
}
+int
+iwmbt_get_tlv(struct libusb_device_handle *hdl,
+ struct iwmbt_tlv *tlv)
+{
+ int ret, transferred;
+ struct iwmbt_hci_event_cmd_compl*event;
+ uint8_t buf[IWMBT_HCI_EVT_COMPL_SIZE(struct iwmbt_tlv) - sizeof(tlv->tlv_len)];
+ uint8_t cmdbuf[offsetof(struct iwmbt_hci_cmd, data) + 1];
+ struct iwmbt_hci_cmd *cmd = (struct iwmbt_hci_cmd *) cmdbuf;
+ cmd->opcode = htole16(0xfc05),
+ cmd->length = 1,
+ cmd->data[0] = 0xff;
+
+ memset(buf, 0, sizeof(buf));
+
+ ret = iwmbt_hci_command(hdl,
+ cmd,
+ buf,
+ sizeof(buf),
+ &transferred,
+ IWMBT_HCI_CMD_TIMEOUT);
+
+ if (ret < 0 || transferred < 1) {
+ iwmbt_debug("Can't get TLV: : code=%d, size=%d",
+ ret,
+ transferred);
+ return (-1);
+ }
+ tlv->tlv_len = transferred - offsetof(struct iwmbt_tlv, tlv_data) - offsetof(struct iwmbt_hci_event_cmd_compl, data);
+
+ event = (struct iwmbt_hci_event_cmd_compl *)buf;
+ if (event->data[0]) {
+ iwmbt_debug("Bad status: : status=%02x", event->data[0]);
+ return -1;
+ }
+ memcpy(tlv, event->data, transferred);
+
+ return (0);
+}
+
int
iwmbt_get_boot_params(struct libusb_device_handle *hdl,
struct iwmbt_boot_params *params)
@@ -495,7 +546,7 @@
}
int
-iwmbt_intel_reset(struct libusb_device_handle *hdl, uint32_t boot_param)
+iwmbt_intel_reset(struct libusb_device_handle *hdl, uint32_t boot_param, bool hard)
{
int ret, transferred = 0;
struct iwmbt_hci_event *event;
@@ -504,6 +555,17 @@
.length = 8,
.data = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 },
};
+ if (hard) {
+ cmd.data[0] = 0x01;
+ cmd.data[1] = 0x01;
+ cmd.data[2] = 0x01;
+ cmd.data[3] = 0x00;
+ } else {
+ cmd.data[0] = 0x00;
+ cmd.data[1] = 0x00;
+ cmd.data[2] = 0x00;
+ cmd.data[3] = 0x01;
+ }
uint8_t buf[IWMBT_HCI_MAX_EVENT_SIZE];
le32enc(cmd.data + 4, boot_param);
@@ -514,20 +576,30 @@
buf,
sizeof(buf),
&transferred,
- IWMBT_HCI_CMD_TIMEOUT);
+ IWMBT_LOADCMPL_TIMEOUT);
- if (ret < 0 || transferred < (int)sizeof(struct iwmbt_hci_event) + 1) {
- iwmbt_debug("Intel Reset command failed: code=%d, size=%d",
- ret,
- transferred);
- return (ret);
- }
+ if (hard) {
+ if (ret < 0) {
+ iwmbt_debug("Intel Hard Reset command failed: code=%d, size=%d",
+ ret,
+ transferred);
+ return (ret);
+ }
+ usleep(150000);
+ } else {
+ if (ret < 0 || transferred < (int)sizeof(struct iwmbt_hci_event) + 1) {
+ iwmbt_debug("Intel Reset command failed: code=%d, size=%d",
+ ret,
+ transferred);
+ return (ret);
+ }
- /* expect Vendor Specific Event 0x02 */
- event = (struct iwmbt_hci_event *)buf;
- if (event->header.event != 0xFF || event->data[0] != 0x02) {
- iwmbt_err("Intel Reset completion event missed");
- return (-1);
+ /* expect Vendor Specific Event 0x02 */
+ event = (struct iwmbt_hci_event *)buf;
+ if (event->header.event != 0xFF || event->data[0] != 0x02) {
+ iwmbt_err("Intel Reset completion event missed. event: %02x, data[0]: %02x", event->header.event, event->data[0]);
+ return (-1);
+ }
}
return (0);
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
@@ -6,6 +6,6 @@
match "subsystem" "DEVICE";
match "type" "ATTACH";
match "vendor" "0x8087";
- match "product" "(0x07dc|0x0a2a|0x0aa7|0x0a2b|0x0aaa|0x0025|0x0026|0x0029)";
+ match "product" "(0x07dc|0x0a2a|0x0aa7|0x0a2b|0x0aaa|0x0025|0x0026|0x0029|0x0032)";
action "/usr/sbin/iwmbtfw -d $cdev -f /usr/local/share/iwmbt-firmware";
};
diff --git a/usr.sbin/bluetooth/iwmbtfw/main.c b/usr.sbin/bluetooth/iwmbtfw/main.c
--- a/usr.sbin/bluetooth/iwmbtfw/main.c
+++ b/usr.sbin/bluetooth/iwmbtfw/main.c
@@ -34,6 +34,7 @@
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -73,6 +74,12 @@
{ .vendor_id = 0x8087, .product_id = 0x0029 },
};
+static struct iwmbt_devid iwmbt_list_tlv[] = {
+
+ { .vendor_id = 0x8087, .product_id = 0x0032 },
+
+};
+
static int
iwmbt_is_7260(struct libusb_device_descriptor *d)
{
@@ -109,9 +116,33 @@
return (0);
}
+static int
+iwmbt_is_tlv(struct libusb_device_descriptor *d)
+{
+ int i;
+
+ /* Search looking for whether it's a TLV device (ie: AX210) */
+ for (i = 0; i < (int) nitems(iwmbt_list_tlv); i++) {
+ if ((iwmbt_list_tlv[i].product_id == d->idProduct) &&
+ (iwmbt_list_tlv[i].vendor_id == d->idVendor)) {
+ iwmbt_info("found TLV");
+ return (1);
+ }
+ }
+
+ /* Not found */
+ return (0);
+}
+
+enum use_method {
+ IWMBT_METHOD_OLD,
+ IWMBT_METHOD_8260,
+ IWMBT_METHOD_TLV,
+};
+
static libusb_device *
iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id,
- int *iwmbt_use_old_method)
+ enum use_method *iwmbt_use_method)
{
libusb_device **list, *dev = NULL, *found = NULL;
struct libusb_device_descriptor d;
@@ -146,7 +177,7 @@
* Take a reference so it's not freed later on.
*/
found = libusb_ref_device(dev);
- *iwmbt_use_old_method = 1;
+ *iwmbt_use_method = IWMBT_METHOD_OLD;
break;
} else
if (iwmbt_is_8260(&d)) {
@@ -154,7 +185,15 @@
* Take a reference so it's not freed later on.
*/
found = libusb_ref_device(dev);
- *iwmbt_use_old_method = 0;
+ *iwmbt_use_method = IWMBT_METHOD_8260;
+ break;
+ } else
+ if (iwmbt_is_tlv(&d)) {
+ /*
+ * Take a reference so it's not freed later on.
+ */
+ found = libusb_ref_device(dev);
+ *iwmbt_use_method = IWMBT_METHOD_TLV;
break;
}
}
@@ -200,6 +239,117 @@
params->otp_bdaddr[0]);
}
+static int
+iwmbt_tlv_foreach(struct iwmbt_tlv *tlv, int (*cb)(struct iwmbt_tlv_field *, void *), void *cbdata)
+{
+ struct iwmbt_tlv_field *f;
+ size_t pos = 0;
+ int rc;
+
+ while ((pos + 2) < tlv->tlv_len) {
+ f = (struct iwmbt_tlv_field *) &tlv->tlv_data[pos];
+ if (pos + f->len >= tlv->tlv_len)
+ break;
+ rc = cb(f, cbdata);
+ if (rc)
+ return rc;
+ pos += offsetof(struct iwmbt_tlv_field, val);
+ pos += f->len;
+ }
+ return 0;
+}
+
+static int
+iwmbt_dump_one_tlv(struct iwmbt_tlv_field *f, void *cbdata __unused)
+{
+ uint32_t tmp;
+
+ switch (f->len) {
+ case 1:
+ iwmbt_info("TLV: 0x%02x = 0x%02x", f->type, f->val[0]);
+ break;
+ case 2:
+ memcpy(&tmp, f->val, f->len);
+ iwmbt_info("TLV: 0x%02x = 0x%04x", f->type, le16toh(*(uint16_t *)&tmp));
+ break;
+ case 4:
+ memcpy(&tmp, f->val, f->len);
+ iwmbt_info("TLV: 0x%02x = 0x%08x", f->type, le32toh(*(uint16_t *)&tmp));
+ break;
+ default:
+ iwmbt_info("TLV: 0x%02x has unhandled length of %d", f->type, f->len);
+ break;
+ }
+ return 0;
+}
+
+static void
+iwmbt_dump_tlv(struct iwmbt_tlv *tlv)
+{
+ iwmbt_tlv_foreach(tlv, iwmbt_dump_one_tlv, NULL);
+}
+
+static int
+iwmbt_parse_one_tlv(struct iwmbt_tlv_field *f, void *cbdata)
+{
+ struct iwmbt_parsed_tlv *parsed = cbdata;
+
+ switch (f->type) {
+ case IWMBT_TLV_TYPE_FNAME_FIRST:
+ if (f->len != sizeof(parsed->fn_first)) {
+ iwmbt_err("Invalid fn_first length %d (expected %zu)", f->len, sizeof(parsed->fn_first));
+ return -1;
+ }
+ memcpy(&parsed->fn_first, f->val, f->len);
+ parsed->parse_state |= 1;
+ break;
+ case IWMBT_TLV_TYPE_FNAME_SECOND:
+ if (f->len != sizeof(parsed->fn_second)) {
+ iwmbt_err("Invalid fn_second length %d (expected %zu)", f->len, sizeof(parsed->fn_second));
+ return -1;
+ }
+ memcpy(&parsed->fn_second, f->val, f->len);
+ parsed->parse_state |= 2;
+ break;
+ case IWMBT_TLV_TYPE_HW_VERSION:
+ if (f->len != sizeof(parsed->hw_version)) {
+ iwmbt_err("Invalid hw_version length %d (expected %zu)", f->len, sizeof(parsed->fn_second));
+ return -1;
+ }
+ memcpy(&parsed->hw_version, f->val, f->len);
+ parsed->parse_state |= 4;
+ break;
+ case IWMBT_TLV_TYPE_RUNNING:
+ if (f->len != sizeof(parsed->running)) {
+ iwmbt_err("Invalid running length %d (expected %zu)", f->len, sizeof(parsed->fn_second));
+ return -1;
+ }
+ memcpy(&parsed->running, f->val, f->len);
+ parsed->parse_state |= 8;
+ break;
+ case IWMBT_TLV_TYPE_SIGTYPE:
+ if (f->len != sizeof(parsed->sigtype)) {
+ iwmbt_err("Invalid sigtype length %d (expected %zu)", f->len, sizeof(parsed->fn_second));
+ return -1;
+ }
+ memcpy(&parsed->sigtype, f->val, f->len);
+ parsed->parse_state |= 16;
+ break;
+ }
+ return 0;
+}
+
+static int
+iwmbt_parse_tlv(struct iwmbt_tlv *tlv, struct iwmbt_parsed_tlv *parsed)
+{
+ parsed->parse_state = 0;
+ if (iwmbt_tlv_foreach(tlv, iwmbt_parse_one_tlv, parsed))
+ return -1;
+ if (parsed->parse_state != 31)
+ return -1;
+ return 0;
+}
+
static int
iwmbt_patch_firmware(libusb_device_handle *hdl, const char *firmware_path)
{
@@ -227,7 +377,7 @@
static int
iwmbt_init_firmware(libusb_device_handle *hdl, const char *firmware_path,
- uint32_t *boot_param)
+ uint32_t *boot_param, bool is_tlv, uint8_t sigtype)
{
struct iwmbt_firmware fw;
int ret;
@@ -241,7 +391,7 @@
}
/* Load in the firmware */
- ret = iwmbt_load_fwfile(hdl, &fw, boot_param);
+ ret = iwmbt_load_fwfile(hdl, &fw, boot_param, is_tlv, sigtype);
if (ret < 0)
iwmbt_debug("Loading firmware file failed");
@@ -317,6 +467,8 @@
libusb_context *ctx = NULL;
libusb_device *dev = NULL;
libusb_device_handle *hdl = NULL;
+ struct iwmbt_tlv tlv;
+ struct iwmbt_parsed_tlv ptlv;
static struct iwmbt_version ver;
static struct iwmbt_boot_params params;
uint32_t boot_param;
@@ -327,7 +479,7 @@
char *firmware_dir = NULL;
char *firmware_path = NULL;
int retcode = 1;
- int iwmbt_use_old_method = 0;
+ enum use_method iwmbt_use_method = IWMBT_METHOD_8260;
/* Parse command line arguments */
while ((n = getopt(argc, argv, "Dd:f:hIm:p:v:")) != -1) {
@@ -372,7 +524,7 @@
iwmbt_debug("opening dev %d.%d", (int) bus_id, (int) dev_id);
/* Find a device based on the bus/dev id */
- dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_use_old_method);
+ dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_use_method);
if (dev == NULL) {
iwmbt_err("device not found");
goto shutdown;
@@ -402,15 +554,29 @@
}
/* Get Intel version */
- r = iwmbt_get_version(hdl, &ver);
+ if (iwmbt_use_method == IWMBT_METHOD_TLV)
+ r = iwmbt_get_tlv(hdl, &tlv);
+ else
+ r = iwmbt_get_version(hdl, &ver);
if (r < 0) {
iwmbt_debug("iwmbt_get_version() failed code %d", r);
goto shutdown;
}
+
+ /* Parse TLV and extract ver stuff from it */
+ if (iwmbt_use_method == IWMBT_METHOD_TLV) {
+ /* TODO: Parse in get? */
+ iwmbt_dump_tlv(&tlv);
+ if (iwmbt_parse_tlv(&tlv, &ptlv))
+ goto shutdown;
+ ver.hw_platform = (ptlv.hw_version & 0x0000ff00) >> 8;
+ ver.hw_variant = (ptlv.hw_version & 0x003f0000) >> 16;
+ }
+
iwmbt_dump_version(&ver);
iwmbt_debug("fw_variant=0x%02x", (int) ver.fw_variant);
- if (iwmbt_use_old_method) {
+ if (iwmbt_use_method == IWMBT_METHOD_OLD) {
/* fw_patch_num = >0 operational mode */
if (ver.fw_patch_num > 0x00) {
@@ -469,7 +635,8 @@
iwmbt_info("Intel Event Mask is set");
(void)iwmbt_exit_manufacturer(hdl, 0x00);
- } else {
+ } else
+ if (iwmbt_use_method == IWMBT_METHOD_8260) {
/* fw_variant = 0x06 bootloader mode / 0x23 operational mode */
if (ver.fw_variant == 0x23) {
@@ -509,14 +676,14 @@
iwmbt_debug("firmware_path = %s", firmware_path);
/* Download firmware and parse it for magic Intel Reset parameter */
- r = iwmbt_init_firmware(hdl, firmware_path, &boot_param);
+ r = iwmbt_init_firmware(hdl, firmware_path, &boot_param, false, 0);
free(firmware_path);
if (r < 0)
goto shutdown;
iwmbt_info("Firmware download complete");
- r = iwmbt_intel_reset(hdl, boot_param);
+ r = iwmbt_intel_reset(hdl, boot_param, false);
if (r < 0) {
iwmbt_debug("iwmbt_intel_reset() failed!");
goto shutdown;
@@ -542,6 +709,67 @@
free(firmware_path);
}
+ /* Set Intel Event mask */
+ r = iwmbt_set_event_mask(hdl);
+ if (r == 0)
+ iwmbt_info("Intel Event Mask is set");
+ } else {
+
+ switch (ver.hw_variant) {
+ case 0x17:
+ break;
+ default:
+ iwmbt_err("unknown hw_variant 0x%02x", (int) ver.hw_variant);
+ goto shutdown;
+ }
+
+ if (ptlv.running != 0x01) {
+ /* Reset to bootloader */
+ // TODO: Possibly always exit here... to reset:
+ r = iwmbt_intel_reset(hdl, 0, true);
+ if (r < 0) {
+ iwmbt_debug("iwmbt_intel_reset() failed!");
+ goto shutdown;
+ }
+ }
+
+ firmware_path = iwmbt_get_fwname_tlv(firmware_dir, &ptlv, "sfi");
+ iwmbt_debug("firmware_path = %s", firmware_path);
+
+ /* Download firmware and parse it for magic Intel Reset parameter */
+ r = iwmbt_init_firmware(hdl, firmware_path, &boot_param, true, ptlv.sigtype);
+ free(firmware_path);
+ if (r < 0)
+ goto shutdown;
+
+ iwmbt_info("Firmware download complete");
+
+ r = iwmbt_intel_reset(hdl, boot_param, false);
+ if (r < 0) {
+ iwmbt_debug("iwmbt_intel_reset() failed!");
+ goto shutdown;
+ }
+
+ iwmbt_info("Firmware operational");
+
+ /* Once device is running in operational mode we can ignore failures */
+ retcode = 0;
+
+ /* Execute Read Intel Version one more time */
+ r = iwmbt_get_version(hdl, &ver);
+ if (r == 0)
+ iwmbt_dump_version(&ver);
+
+ /* Apply the device configuration (DDC) parameters */
+ firmware_path = iwmbt_get_fwname_tlv(firmware_dir, &ptlv, "ddc");
+ iwmbt_debug("ddc_path = %s", firmware_path);
+ if (firmware_path != NULL) {
+ r = iwmbt_init_ddc(hdl, firmware_path);
+ if (r == 0)
+ iwmbt_info("DDC download complete");
+ free(firmware_path);
+ }
+
/* Set Intel Event mask */
r = iwmbt_set_event_mask(hdl);
if (r == 0)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 3, 11:42 PM (7 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16956301
Default Alt Text
D44861.id137444.diff (21 KB)
Attached To
Mode
D44861: Initial cut at Intel AX210 bluetooth support
Attached
Detach File
Event Timeline
Log In to Comment