Page MenuHomeFreeBSD

D44861.id137444.diff
No OneTemporary

D44861.id137444.diff

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

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)

Event Timeline