aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Michaud-Boudreault <pitwuu@gmail.com>2021-05-04 23:48:21 +0000
committerVladimir Kondratyev <wulf@FreeBSD.org>2021-05-04 23:50:32 +0000
commitfe70d7b26d7a98b17e315bc3455bee267c618b4e (patch)
treed106f18ff25379ffbd307382600e69475e5cb938
parent15c0aaf51703cc102940aa647d623ec8ffbe9259 (diff)
downloadsrc-fe70d7b26d7a98b17e315bc3455bee267c618b4e.tar.gz
src-fe70d7b26d7a98b17e315bc3455bee267c618b4e.zip
iwmbtfw(8): Add support for Intel 7260/7265 bluetooth adapter firmwares
To use it comms/iwmbt-firmware port should be updated to 20210315 version. Submitted by: Philippe Michaud-Boudreault <pitwuu@gmail.com> Tested by: Helge Oldach <freebsd@oldach.net> Reviewed by: wulf PR: 228787 MFC after: 2 weeks
-rw-r--r--usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c14
-rw-r--r--usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c189
-rw-r--r--usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h5
-rw-r--r--usr.sbin/bluetooth/iwmbtfw/iwmbtfw.810
-rw-r--r--usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf2
-rw-r--r--usr.sbin/bluetooth/iwmbtfw/main.c253
6 files changed, 401 insertions, 72 deletions
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
index 7764f8bc4ac3..fc93ce094adc 100644
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
@@ -119,6 +119,20 @@ iwmbt_get_fwname(struct iwmbt_version *ver, struct iwmbt_boot_params *params,
char *fwname;
switch (ver->hw_variant) {
+ case 0x07: /* 7260 */
+ asprintf(&fwname, "%s/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.%s",
+ prefix,
+ le16toh(ver->hw_platform),
+ le16toh(ver->hw_variant),
+ le16toh(ver->hw_revision),
+ le16toh(ver->fw_variant),
+ le16toh(ver->fw_revision),
+ le16toh(ver->fw_build_num),
+ le16toh(ver->fw_build_ww),
+ le16toh(ver->fw_build_yy),
+ suffix);
+ break;
+
case 0x0b: /* 8260 */
case 0x0c: /* 8265 */
asprintf(&fwname, "%s/ibt-%u-%u.%s",
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
index af48e038340f..f4272548d560 100644
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
@@ -27,7 +27,7 @@
* $FreeBSD$
*/
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/endian.h>
#include <sys/stat.h>
@@ -127,6 +127,125 @@ iwmbt_hci_command(struct libusb_device_handle *hdl, struct iwmbt_hci_cmd *cmd,
}
int
+iwmbt_patch_fwfile(struct libusb_device_handle *hdl,
+ const struct iwmbt_firmware *fw)
+{
+ int ret, transferred;
+ struct iwmbt_firmware fw_job = *fw;
+ uint16_t cmd_opcode;
+ uint8_t cmd_length;
+ uint8_t cmd_buf[IWMBT_HCI_MAX_CMD_SIZE];
+ uint8_t evt_code;
+ uint8_t evt_length;
+ uint8_t evt_buf[IWMBT_HCI_MAX_EVENT_SIZE];
+ int skip_patch = 0;
+
+ for (;;) {
+ skip_patch = 0;
+
+ if (fw_job.len < 4)
+ break;
+
+ if (fw_job.buf[0] != 0x01) {
+ iwmbt_err("Invalid firmware, expected HCI command (%d)",
+ fw_job.buf[0]);
+ return (-1);
+ }
+
+ /* Advance by one. */
+ fw_job.buf++;
+ fw_job.len--;
+
+ /* Load in the HCI command to perform. */
+ cmd_opcode = le16dec(fw_job.buf);
+ cmd_length = fw_job.buf[2];
+ memcpy(cmd_buf, fw_job.buf, 3);
+
+ iwmbt_debug("opcode=%04x, len=%02x", cmd_opcode, cmd_length);
+
+ /* For some reason the command 0xfc2f hangs up my card. */
+ if (cmd_opcode == 0xfc2f)
+ skip_patch = 1;
+
+ /* Advance by three. */
+ fw_job.buf += 3;
+ fw_job.len -= 3;
+
+ if (fw_job.len < cmd_length)
+ cmd_length = fw_job.len;
+
+ /* Copy data to HCI command buffer. */
+ memcpy(cmd_buf + 3, fw_job.buf,
+ MIN(cmd_length, IWMBT_HCI_MAX_CMD_SIZE - 3));
+
+ /* Advance by data length. */
+ fw_job.buf += cmd_length;
+ fw_job.len -= cmd_length;
+
+ /*
+ * Every command has its associated event: data must match
+ * what is recorded in the firmware file. Perform that check
+ * now.
+ *
+ * Some commands are mapped to more than one event sequence,
+ * in that case we can drop the non-patch commands, as we
+ * probably don't need them for operation of the card.
+ *
+ */
+
+ for (;;) {
+ /* Is this the end of the file? */
+ if (fw_job.len < 3)
+ break;
+
+ if (fw_job.buf[0] != 0x02)
+ break;
+
+ /* Advance by one. */
+ fw_job.buf++;
+ fw_job.len--;
+
+ /* Load in the HCI event. */
+ evt_code = fw_job.buf[0];
+ evt_length = fw_job.buf[1];
+
+ /* Advance by two. */
+ fw_job.buf += 2;
+ fw_job.len -= 2;
+
+ /* Prepare HCI event buffer. */
+ memset(evt_buf, 0, IWMBT_HCI_MAX_EVENT_SIZE);
+
+ iwmbt_debug("event=%04x, len=%02x",
+ evt_code, evt_length);
+
+ /* Advance by data length. */
+ fw_job.buf += evt_length;
+ fw_job.len -= evt_length;
+
+ if (skip_patch == 0) {
+ ret = iwmbt_hci_command(hdl,
+ (struct iwmbt_hci_cmd *)cmd_buf,
+ evt_buf,
+ IWMBT_HCI_MAX_EVENT_SIZE,
+ &transferred,
+ IWMBT_HCI_CMD_TIMEOUT);
+
+ if (ret < 0) {
+ iwmbt_debug("Can't send patch: "
+ "code=%d, size=%d",
+ ret,
+ transferred);
+ return (-1);
+ }
+ }
+ }
+ }
+
+ return (0);
+}
+
+int
iwmbt_load_fwfile(struct libusb_device_handle *hdl,
const struct iwmbt_firmware *fw, uint32_t *boot_param)
{
@@ -218,6 +337,74 @@ iwmbt_load_fwfile(struct libusb_device_handle *hdl,
}
int
+iwmbt_enter_manufacturer(struct libusb_device_handle *hdl)
+{
+ int ret, transferred;
+ static struct iwmbt_hci_cmd cmd = {
+ .opcode = htole16(0xfc11),
+ .length = 2,
+ .data = { 0x01, 0x00 },
+ };
+ uint8_t buf[IWMBT_HCI_MAX_EVENT_SIZE];
+
+ ret = iwmbt_hci_command(hdl,
+ &cmd,
+ buf,
+ sizeof(buf),
+ &transferred,
+ IWMBT_HCI_CMD_TIMEOUT);
+
+ if (ret < 0) {
+ iwmbt_debug("Can't enter manufacturer mode: code=%d, size=%d",
+ ret,
+ transferred);
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+iwmbt_exit_manufacturer(struct libusb_device_handle *hdl, int mode)
+{
+ int ret, transferred;
+ static struct iwmbt_hci_cmd cmd = {
+ .opcode = htole16(0xfc11),
+ .length = 2,
+ .data = { 0x00, 0x00 },
+ };
+ uint8_t buf[IWMBT_HCI_MAX_EVENT_SIZE];
+
+ /*
+ * The mode sets the type of reset we want to perform:
+ * 0x00: simply exit manufacturer mode without a reset.
+ * 0x01: exit manufacturer mode with a reset and patches disabled
+ * 0x02: exit manufacturer mode with a reset and patches enabled
+ */
+ if (mode > 2) {
+ iwmbt_debug("iwmbt_exit_manufacturer(): unknown mode (%d)",
+ mode);
+ }
+ cmd.data[1] = mode;
+
+ ret = iwmbt_hci_command(hdl,
+ &cmd,
+ buf,
+ sizeof(buf),
+ &transferred,
+ IWMBT_HCI_CMD_TIMEOUT);
+
+ if (ret < 0) {
+ iwmbt_debug("Can't exit manufacturer mode: code=%d, size=%d",
+ ret,
+ transferred);
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
iwmbt_get_version(struct libusb_device_handle *hdl,
struct iwmbt_version *version)
{
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
index 6a87f499fa26..5bc1d15181cd 100644
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
@@ -73,8 +73,13 @@ struct iwmbt_hci_event_cmd_compl {
#define IWMBT_HCI_CMD_TIMEOUT 2000 /* ms */
#define IWMBT_LOADCMPL_TIMEOUT 5000 /* ms */
+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);
+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_boot_params(struct libusb_device_handle *hdl,
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.8 b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.8
index 3afbf54793f9..10e68040e0e4 100644
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.8
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.8
@@ -1,5 +1,6 @@
.\" Copyright (c) 2013, 2016 Adrian Chadd <adrian@freebsd.org>
.\" Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
+.\" Copyright (c) 2021 Philippe Michaud-Boudreault <pitwuu@gmail.com>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -24,12 +25,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 4, 2019
+.Dd May 3, 2021
.Dt IWMBTFW 8
.Os
.Sh NAME
.Nm iwmbtfw
-.Nd firmware download utility for Intel Wireless 8260/8265 chip based Bluetooth
+.Nd firmware download utility for Intel Wireless 7260/8260/8265 chip based Bluetooth
USB devices
.Sh SYNOPSIS
.Nm
@@ -46,7 +47,7 @@ device.
.Pp
This utility will
.Em only
-work with Intel Wireless 8260/8265 chip based Bluetooth USB devices and some of
+work with Intel Wireless 7260/8260/8265 chip based Bluetooth USB devices and some of
their successors.
The identification is currently based on USB vendor ID/product ID pair.
The vendor ID should be 0x8087
@@ -91,6 +92,9 @@ utility used as firmware downloader template and on Linux btintel driver
source code.
It is written by
.An Vladimir Kondratyev Aq Mt wulf@FreeBSD.org .
+.Pp
+Support for the 7260 card added by
+.An Philippe Michaud-Boudreault Aq Mt pitwuu@gmail.com .
.Sh BUGS
Most likely.
Please report if found.
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
index 4bd1f020237c..6b417089c68b 100644
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
@@ -7,6 +7,6 @@ notify 100 {
match "subsystem" "DEVICE";
match "type" "ATTACH";
match "vendor" "0x8087";
- match "product" "(0x0a2b|0x0aaa|0x0025|0x0026|0x0029)";
+ match "product" "(0x07dc|0x0a2a|0x0aa7|0x0a2b|0x0aaa|0x0025|0x0026|0x0029)";
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
index ecd9d226b91f..3476e3fcd613 100644
--- a/usr.sbin/bluetooth/iwmbtfw/main.c
+++ b/usr.sbin/bluetooth/iwmbtfw/main.c
@@ -57,7 +57,15 @@ struct iwmbt_devid {
uint16_t vendor_id;
};
-static struct iwmbt_devid iwmbt_list[] = {
+static struct iwmbt_devid iwmbt_list_72xx[] = {
+
+ /* Intel Wireless 7260/7265 and successors */
+ { .vendor_id = 0x8087, .product_id = 0x07dc },
+ { .vendor_id = 0x8087, .product_id = 0x0a2a },
+ { .vendor_id = 0x8087, .product_id = 0x0aa7 },
+};
+
+static struct iwmbt_devid iwmbt_list_82xx[] = {
/* Intel Wireless 8260/8265 and successors */
{ .vendor_id = 0x8087, .product_id = 0x0a2b },
@@ -68,14 +76,32 @@ static struct iwmbt_devid iwmbt_list[] = {
};
static int
+iwmbt_is_7260(struct libusb_device_descriptor *d)
+{
+ int i;
+
+ /* Search looking for whether it's an 7260/7265 */
+ for (i = 0; i < (int) nitems(iwmbt_list_72xx); i++) {
+ if ((iwmbt_list_72xx[i].product_id == d->idProduct) &&
+ (iwmbt_list_72xx[i].vendor_id == d->idVendor)) {
+ iwmbt_info("found 7260/7265");
+ return (1);
+ }
+ }
+
+ /* Not found */
+ return (0);
+}
+
+static int
iwmbt_is_8260(struct libusb_device_descriptor *d)
{
int i;
/* Search looking for whether it's an 8260/8265 */
- for (i = 0; i < (int) nitems(iwmbt_list); i++) {
- if ((iwmbt_list[i].product_id == d->idProduct) &&
- (iwmbt_list[i].vendor_id == d->idVendor)) {
+ for (i = 0; i < (int) nitems(iwmbt_list_82xx); i++) {
+ if ((iwmbt_list_82xx[i].product_id == d->idProduct) &&
+ (iwmbt_list_82xx[i].vendor_id == d->idVendor)) {
iwmbt_info("found 8260/8265");
return (1);
}
@@ -86,7 +112,8 @@ iwmbt_is_8260(struct libusb_device_descriptor *d)
}
static libusb_device *
-iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id)
+iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id,
+ int *iwmbt_use_old_method)
{
libusb_device **list, *dev = NULL, *found = NULL;
struct libusb_device_descriptor d;
@@ -116,11 +143,20 @@ iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id)
}
/* Match on the vendor/product id */
+ if (iwmbt_is_7260(&d)) {
+ /*
+ * Take a reference so it's not freed later on.
+ */
+ found = libusb_ref_device(dev);
+ *iwmbt_use_old_method = 1;
+ break;
+ } else
if (iwmbt_is_8260(&d)) {
/*
* Take a reference so it's not freed later on.
*/
found = libusb_ref_device(dev);
+ *iwmbt_use_old_method = 0;
break;
}
}
@@ -167,6 +203,31 @@ iwmbt_dump_boot_params(struct iwmbt_boot_params *params)
}
static int
+iwmbt_patch_firmware(libusb_device_handle *hdl, const char *firmware_path)
+{
+ struct iwmbt_firmware fw;
+ int ret;
+
+ iwmbt_debug("loading %s", firmware_path);
+
+ /* Read in the firmware */
+ if (iwmbt_fw_read(&fw, firmware_path) <= 0) {
+ iwmbt_debug("iwmbt_fw_read() failed");
+ return (-1);
+ }
+
+ /* Load in the firmware */
+ ret = iwmbt_patch_fwfile(hdl, &fw);
+ if (ret < 0)
+ iwmbt_debug("Loading firmware file failed");
+
+ /* free it */
+ iwmbt_fw_free(&fw);
+
+ return (ret);
+}
+
+static int
iwmbt_init_firmware(libusb_device_handle *hdl, const char *firmware_path,
uint32_t *boot_param)
{
@@ -268,6 +329,7 @@ main(int argc, char *argv[])
char *firmware_dir = NULL;
char *firmware_path = NULL;
int retcode = 1;
+ int iwmbt_use_old_method = 0;
/* Parse command line arguments */
while ((n = getopt(argc, argv, "Dd:f:hIm:p:v:")) != -1) {
@@ -312,7 +374,7 @@ main(int argc, char *argv[])
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);
+ dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_use_old_method);
if (dev == NULL) {
iwmbt_err("device not found");
goto shutdown;
@@ -344,87 +406,144 @@ main(int argc, char *argv[])
/* Get Intel version */
r = iwmbt_get_version(hdl, &ver);
if (r < 0) {
- iwmbt_debug("iwmbt_get_version() failedL code %d", r);
+ iwmbt_debug("iwmbt_get_version() failed code %d", r);
goto shutdown;
}
iwmbt_dump_version(&ver);
iwmbt_debug("fw_variant=0x%02x", (int) ver.fw_variant);
- /* fw_variant = 0x06 bootloader mode / 0x23 operational mode */
- if (ver.fw_variant == 0x23) {
- iwmbt_info("Firmware has already been downloaded");
+ if (iwmbt_use_old_method) {
+
+ /* fw_patch_num = >0 operational mode */
+ if (ver.fw_patch_num > 0x00) {
+ iwmbt_info("Firmware has already been downloaded");
+ retcode = 0;
+ goto reset;
+ }
+
+ /* Default the firmware path */
+ if (firmware_dir == NULL)
+ firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
+
+ firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "bseq");
+ if (firmware_path == NULL)
+ goto shutdown;
+
+ iwmbt_debug("firmware_path = %s", firmware_path);
+
+ /* Enter manufacturer mode */
+ r = iwmbt_enter_manufacturer(hdl);
+ if (r < 0) {
+ iwmbt_debug("iwmbt_enter_manufacturer() failed code %d", r);
+ goto shutdown;
+ }
+
+ /* Download firmware and parse it for magic Intel Reset parameter */
+ r = iwmbt_patch_firmware(hdl, firmware_path);
+ free(firmware_path);
+ if (r < 0)
+ goto shutdown;
+
+ iwmbt_info("Firmware download complete");
+
+ /* Exit manufacturer mode */
+ r = iwmbt_exit_manufacturer(hdl, 0x02);
+ if (r < 0) {
+ iwmbt_debug("iwmbt_exit_manufacturer() failed code %d", r);
+ goto shutdown;
+ }
+
+ /* Once device is running in operational mode we can ignore failures */
retcode = 0;
- goto reset;
- }
- if (ver.fw_variant != 0x06){
- iwmbt_err("unknown fw_variant 0x%02x", (int) ver.fw_variant);
- goto shutdown;
- }
+ /* Execute Read Intel Version one more time */
+ r = iwmbt_get_version(hdl, &ver);
+ if (r == 0)
+ iwmbt_dump_version(&ver);
- /* Read Intel Secure Boot Params */
- r = iwmbt_get_boot_params(hdl, &params);
- if (r < 0) {
- iwmbt_debug("iwmbt_get_boot_params() failed!");
- goto shutdown;
- }
- iwmbt_dump_boot_params(&params);
+ /* Set Intel Event mask */
+ r = iwmbt_set_event_mask(hdl);
+ if (r == 0)
+ iwmbt_info("Intel Event Mask is set");
- /* Check if firmware fragments are ACKed with a cmd complete event */
- if (params.limited_cce != 0x00) {
- iwmbt_err("Unsupported Intel firmware loading method (%u)",
- params.limited_cce);
- goto shutdown;
- }
+ } else {
- /* Default the firmware path */
- if (firmware_dir == NULL)
- firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
+ /* fw_variant = 0x06 bootloader mode / 0x23 operational mode */
+ if (ver.fw_variant == 0x23) {
+ iwmbt_info("Firmware has already been downloaded");
+ retcode = 0;
+ goto reset;
+ }
- firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "sfi");
- if (firmware_path == NULL)
- goto shutdown;
+ if (ver.fw_variant != 0x06){
+ iwmbt_err("unknown fw_variant 0x%02x", (int) ver.fw_variant);
+ goto shutdown;
+ }
- iwmbt_debug("firmware_path = %s", firmware_path);
+ /* Read Intel Secure Boot Params */
+ r = iwmbt_get_boot_params(hdl, &params);
+ if (r < 0) {
+ iwmbt_debug("iwmbt_get_boot_params() failed!");
+ goto shutdown;
+ }
+ iwmbt_dump_boot_params(&params);
- /* Download firmware and parse it for magic Intel Reset parameter */
- r = iwmbt_init_firmware(hdl, firmware_path, &boot_param);
- free(firmware_path);
- if (r < 0)
- goto shutdown;
+ /* Check if firmware fragments are ACKed with a cmd complete event */
+ if (params.limited_cce != 0x00) {
+ iwmbt_err("Unsupported Intel firmware loading method (%u)",
+ params.limited_cce);
+ goto shutdown;
+ }
- iwmbt_info("Firmware download complete");
+ /* Default the firmware path */
+ if (firmware_dir == NULL)
+ firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH);
- r = iwmbt_intel_reset(hdl, boot_param);
- if (r < 0) {
- iwmbt_debug("iwmbt_intel_reset() failed!");
- goto shutdown;
- }
+ firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "sfi");
+ if (firmware_path == NULL)
+ goto shutdown;
- iwmbt_info("Firmware operational");
+ iwmbt_debug("firmware_path = %s", firmware_path);
- /* Once device is running in operational mode we can ignore failures */
- retcode = 0;
+ /* Download firmware and parse it for magic Intel Reset parameter */
+ r = iwmbt_init_firmware(hdl, firmware_path, &boot_param);
+ free(firmware_path);
+ if (r < 0)
+ goto shutdown;
- /* 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(&ver, &params, firmware_dir, "ddc");
- iwmbt_debug("ddc_path = %s", firmware_path);
- if (firmware_path != NULL) {
- r = iwmbt_init_ddc(hdl, firmware_path);
+ iwmbt_info("Firmware download complete");
+
+ r = iwmbt_intel_reset(hdl, boot_param);
+ 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_info("DDC download complete");
- free(firmware_path);
- }
+ iwmbt_dump_version(&ver);
+
+ /* Apply the device configuration (DDC) parameters */
+ firmware_path = iwmbt_get_fwname(&ver, &params, firmware_dir, "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)
- iwmbt_info("Intel Event Mask is set");
+ /* Set Intel Event mask */
+ r = iwmbt_set_event_mask(hdl);
+ if (r == 0)
+ iwmbt_info("Intel Event Mask is set");
+ }
reset: