1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2013 Adrian Chadd <adrian@freebsd.org> 5 * Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org> 6 * Copyright (c) 2023 Future Crew LLC. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/stat.h> 32 #include <sys/endian.h> 33 34 #include <err.h> 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <libgen.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include <libusb.h> 44 45 #include "iwmbt_fw.h" 46 #include "iwmbt_hw.h" 47 #include "iwmbt_dbg.h" 48 49 #define _DEFAULT_IWMBT_FIRMWARE_PATH "/usr/share/firmware/intel" 50 51 int iwmbt_do_debug = 0; 52 int iwmbt_do_info = 0; 53 54 enum iwmbt_device { 55 IWMBT_DEVICE_UNKNOWN, 56 IWMBT_DEVICE_7260, 57 IWMBT_DEVICE_8260, 58 IWMBT_DEVICE_9260, 59 }; 60 61 struct iwmbt_devid { 62 uint16_t product_id; 63 uint16_t vendor_id; 64 enum iwmbt_device device; 65 }; 66 67 static struct iwmbt_devid iwmbt_list[] = { 68 69 /* Intel Wireless 7260/7265 and successors */ 70 { .vendor_id = 0x8087, .product_id = 0x07dc, .device = IWMBT_DEVICE_7260 }, 71 { .vendor_id = 0x8087, .product_id = 0x0a2a, .device = IWMBT_DEVICE_7260 }, 72 { .vendor_id = 0x8087, .product_id = 0x0aa7, .device = IWMBT_DEVICE_7260 }, 73 74 /* Intel Wireless 8260/8265 and successors */ 75 { .vendor_id = 0x8087, .product_id = 0x0a2b, .device = IWMBT_DEVICE_8260 }, 76 { .vendor_id = 0x8087, .product_id = 0x0aaa, .device = IWMBT_DEVICE_8260 }, 77 { .vendor_id = 0x8087, .product_id = 0x0025, .device = IWMBT_DEVICE_8260 }, 78 { .vendor_id = 0x8087, .product_id = 0x0026, .device = IWMBT_DEVICE_8260 }, 79 { .vendor_id = 0x8087, .product_id = 0x0029, .device = IWMBT_DEVICE_8260 }, 80 81 /* Intel Wireless 9260/9560 and successors */ 82 { .vendor_id = 0x8087, .product_id = 0x0032, .device = IWMBT_DEVICE_9260 }, 83 { .vendor_id = 0x8087, .product_id = 0x0033, .device = IWMBT_DEVICE_9260 }, 84 }; 85 86 static enum iwmbt_device 87 iwmbt_is_supported(struct libusb_device_descriptor *d) 88 { 89 int i; 90 91 /* Search looking for whether it's an 7260/7265 */ 92 for (i = 0; i < (int) nitems(iwmbt_list); i++) { 93 if ((iwmbt_list[i].product_id == d->idProduct) && 94 (iwmbt_list[i].vendor_id == d->idVendor)) { 95 iwmbt_info("found iwmbtfw compatible"); 96 return (iwmbt_list[i].device); 97 } 98 } 99 100 /* Not found */ 101 return (IWMBT_DEVICE_UNKNOWN); 102 } 103 104 static libusb_device * 105 iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id, 106 enum iwmbt_device *iwmbt_device) 107 { 108 libusb_device **list, *dev = NULL, *found = NULL; 109 struct libusb_device_descriptor d; 110 enum iwmbt_device device; 111 ssize_t cnt, i; 112 int r; 113 114 cnt = libusb_get_device_list(ctx, &list); 115 if (cnt < 0) { 116 iwmbt_err("libusb_get_device_list() failed: code %lld", 117 (long long int) cnt); 118 return (NULL); 119 } 120 121 /* 122 * Scan through USB device list. 123 */ 124 for (i = 0; i < cnt; i++) { 125 dev = list[i]; 126 if (bus_id == libusb_get_bus_number(dev) && 127 dev_id == libusb_get_device_address(dev)) { 128 /* Get the device descriptor for this device entry */ 129 r = libusb_get_device_descriptor(dev, &d); 130 if (r != 0) { 131 iwmbt_err("libusb_get_device_descriptor: %s", 132 libusb_strerror(r)); 133 break; 134 } 135 136 /* Match on the vendor/product id */ 137 device = iwmbt_is_supported(&d); 138 if (device != IWMBT_DEVICE_UNKNOWN) { 139 /* 140 * Take a reference so it's not freed later on. 141 */ 142 found = libusb_ref_device(dev); 143 *iwmbt_device = device; 144 break; 145 } 146 } 147 } 148 149 libusb_free_device_list(list, 1); 150 return (found); 151 } 152 153 static void 154 iwmbt_dump_version(struct iwmbt_version *ver) 155 { 156 iwmbt_info("status 0x%02x", ver->status); 157 iwmbt_info("hw_platform 0x%02x", ver->hw_platform); 158 iwmbt_info("hw_variant 0x%02x", ver->hw_variant); 159 iwmbt_info("hw_revision 0x%02x", ver->hw_revision); 160 iwmbt_info("fw_variant 0x%02x", ver->fw_variant); 161 iwmbt_info("fw_revision 0x%02x", ver->fw_revision); 162 iwmbt_info("fw_build_num 0x%02x", ver->fw_build_num); 163 iwmbt_info("fw_build_ww 0x%02x", ver->fw_build_ww); 164 iwmbt_info("fw_build_yy 0x%02x", ver->fw_build_yy); 165 iwmbt_info("fw_patch_num 0x%02x", ver->fw_patch_num); 166 } 167 168 static void 169 iwmbt_dump_boot_params(struct iwmbt_boot_params *params) 170 { 171 iwmbt_info("Device revision: %u", le16toh(params->dev_revid)); 172 iwmbt_info("Secure Boot: %s", params->secure_boot ? "on" : "off"); 173 iwmbt_info("OTP lock: %s", params->otp_lock ? "on" : "off"); 174 iwmbt_info("API lock: %s", params->api_lock ? "on" : "off"); 175 iwmbt_info("Debug lock: %s", params->debug_lock ? "on" : "off"); 176 iwmbt_info("Minimum firmware build %u week %u year %u", 177 params->min_fw_build_nn, 178 params->min_fw_build_cw, 179 2000 + params->min_fw_build_yy); 180 iwmbt_info("OTC BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x", 181 params->otp_bdaddr[5], 182 params->otp_bdaddr[4], 183 params->otp_bdaddr[3], 184 params->otp_bdaddr[2], 185 params->otp_bdaddr[1], 186 params->otp_bdaddr[0]); 187 } 188 189 static void 190 iwmbt_dump_version_tlv(struct iwmbt_version_tlv *ver) 191 { 192 iwmbt_info("cnvi_top 0x%08x", ver->cnvi_top); 193 iwmbt_info("cnvr_top 0x%08x", ver->cnvr_top); 194 iwmbt_info("cnvi_bt 0x%08x", ver->cnvi_bt); 195 iwmbt_info("cnvr_bt 0x%08x", ver->cnvr_bt); 196 iwmbt_info("dev_rev_id 0x%04x", ver->dev_rev_id); 197 iwmbt_info("img_type 0x%02x", ver->img_type); 198 iwmbt_info("timestamp 0x%04x", ver->timestamp); 199 iwmbt_info("build_type 0x%02x", ver->build_type); 200 iwmbt_info("build_num 0x%08x", ver->build_num); 201 iwmbt_info("Secure Boot: %s", ver->secure_boot ? "on" : "off"); 202 iwmbt_info("OTP lock: %s", ver->otp_lock ? "on" : "off"); 203 iwmbt_info("API lock: %s", ver->api_lock ? "on" : "off"); 204 iwmbt_info("Debug lock: %s", ver->debug_lock ? "on" : "off"); 205 iwmbt_info("Minimum firmware build %u week %u year %u", 206 ver->min_fw_build_nn, 207 ver->min_fw_build_cw, 208 2000 + ver->min_fw_build_yy); 209 iwmbt_info("limited_cce 0x%02x", ver->limited_cce); 210 iwmbt_info("sbe_type 0x%02x", ver->sbe_type); 211 iwmbt_info("OTC BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x", 212 ver->otp_bd_addr.b[5], 213 ver->otp_bd_addr.b[4], 214 ver->otp_bd_addr.b[3], 215 ver->otp_bd_addr.b[2], 216 ver->otp_bd_addr.b[1], 217 ver->otp_bd_addr.b[0]); 218 if (ver->img_type == TLV_IMG_TYPE_BOOTLOADER || 219 ver->img_type == TLV_IMG_TYPE_OPERATIONAL) 220 iwmbt_info("%s timestamp %u.%u buildtype %u build %u", 221 (ver->img_type == TLV_IMG_TYPE_BOOTLOADER ? 222 "Bootloader" : "Firmware"), 223 2000 + (ver->timestamp >> 8), 224 ver->timestamp & 0xff, 225 ver->build_type, 226 ver->build_num); 227 } 228 229 230 static int 231 iwmbt_init_firmware(libusb_device_handle *hdl, const char *firmware_path, 232 uint32_t *boot_param, uint8_t hw_variant, uint8_t sbe_type) 233 { 234 struct iwmbt_firmware fw; 235 int header_len, ret = -1; 236 237 iwmbt_debug("loading %s", firmware_path); 238 239 /* Read in the firmware */ 240 if (iwmbt_fw_read(&fw, firmware_path) <= 0) { 241 iwmbt_debug("iwmbt_fw_read() failed"); 242 return (-1); 243 } 244 245 iwmbt_debug("Firmware file size=%d", fw.len); 246 247 if (hw_variant <= 0x14) { 248 /* 249 * Hardware variants 0x0b, 0x0c, 0x11 - 0x14 .sfi file have 250 * a RSA header of 644 bytes followed by Command Buffer. 251 */ 252 header_len = RSA_HEADER_LEN; 253 if (fw.len < header_len) { 254 iwmbt_err("Invalid size of firmware file (%d)", fw.len); 255 ret = -1; 256 goto exit; 257 } 258 259 /* Check if the CSS Header version is RSA(0x00010000) */ 260 if (le32dec(fw.buf + CSS_HEADER_OFFSET) != 0x00010000) { 261 iwmbt_err("Invalid CSS Header version"); 262 ret = -1; 263 goto exit; 264 } 265 266 /* Only RSA secure boot engine supported */ 267 if (sbe_type != 0x00) { 268 iwmbt_err("Invalid SBE type for hardware variant (%d)", 269 hw_variant); 270 ret = -1; 271 goto exit; 272 } 273 274 } else if (hw_variant >= 0x17) { 275 /* 276 * Hardware variants 0x17, 0x18 onwards support both RSA and 277 * ECDSA secure boot engine. As a result, the corresponding sfi 278 * file will have RSA header of 644, ECDSA header of 320 bytes 279 * followed by Command Buffer. 280 */ 281 header_len = ECDSA_OFFSET + ECDSA_HEADER_LEN; 282 if (fw.len < header_len) { 283 iwmbt_err("Invalid size of firmware file (%d)", fw.len); 284 ret = -1; 285 goto exit; 286 } 287 288 /* Check if CSS header for ECDSA follows the RSA header */ 289 if (fw.buf[ECDSA_OFFSET] != 0x06) { 290 ret = -1; 291 goto exit; 292 } 293 294 /* Check if the CSS Header version is ECDSA(0x00020000) */ 295 if (le32dec(fw.buf + ECDSA_OFFSET + CSS_HEADER_OFFSET) != 0x00020000) { 296 iwmbt_err("Invalid CSS Header version"); 297 ret = -1; 298 goto exit; 299 } 300 } 301 302 /* Load in the CSS header */ 303 if (sbe_type == 0x00) 304 ret = iwmbt_load_rsa_header(hdl, &fw); 305 else if (sbe_type == 0x01) 306 ret = iwmbt_load_ecdsa_header(hdl, &fw); 307 if (ret < 0) 308 goto exit; 309 310 /* Load in the Command Buffer */ 311 ret = iwmbt_load_fwfile(hdl, &fw, boot_param, header_len); 312 313 exit: 314 /* free firmware */ 315 iwmbt_fw_free(&fw); 316 317 return (ret); 318 } 319 320 static int 321 iwmbt_init_ddc(libusb_device_handle *hdl, const char *ddc_path) 322 { 323 struct iwmbt_firmware ddc; 324 int ret; 325 326 iwmbt_debug("loading %s", ddc_path); 327 328 /* Read in the DDC file */ 329 if (iwmbt_fw_read(&ddc, ddc_path) <= 0) { 330 iwmbt_debug("iwmbt_fw_read() failed"); 331 return (-1); 332 } 333 334 /* Load in the DDC file */ 335 ret = iwmbt_load_ddc(hdl, &ddc); 336 if (ret < 0) 337 iwmbt_debug("Loading DDC file failed"); 338 339 /* free it */ 340 iwmbt_fw_free(&ddc); 341 342 return (ret); 343 } 344 345 /* 346 * Parse ugen name and extract device's bus and address 347 */ 348 349 static int 350 parse_ugen_name(char const *ugen, uint8_t *bus, uint8_t *addr) 351 { 352 char *ep; 353 354 if (strncmp(ugen, "ugen", 4) != 0) 355 return (-1); 356 357 *bus = (uint8_t) strtoul(ugen + 4, &ep, 10); 358 if (*ep != '.') 359 return (-1); 360 361 *addr = (uint8_t) strtoul(ep + 1, &ep, 10); 362 if (*ep != '\0') 363 return (-1); 364 365 return (0); 366 } 367 368 static void 369 usage(void) 370 { 371 fprintf(stderr, 372 "Usage: iwmbtfw [-DI] -d ugenX.Y [-f firmware path]\n"); 373 fprintf(stderr, " -D: enable debugging\n"); 374 fprintf(stderr, " -d: device to operate upon\n"); 375 fprintf(stderr, " -f: firmware path (defaults to %s)\n", 376 _DEFAULT_IWMBT_FIRMWARE_PATH); 377 fprintf(stderr, " -I: enable informational output\n"); 378 exit(127); 379 } 380 381 382 383 /* 384 * Returns 0 on success. 385 */ 386 static int 387 handle_7260(libusb_device_handle *hdl, char *firmware_dir) 388 { 389 int r; 390 char *firmware_path; 391 struct iwmbt_version ver; 392 struct iwmbt_firmware fw; 393 394 r = iwmbt_get_version(hdl, &ver); 395 if (r < 0) { 396 iwmbt_debug("iwmbt_get_version() failed code %d", r); 397 return 1; 398 } 399 iwmbt_dump_version(&ver); 400 iwmbt_debug("fw_patch_num=0x%02x", (int) ver.fw_patch_num); 401 402 /* fw_patch_num = >0 operational mode */ 403 if (ver.fw_patch_num > 0x00) { 404 iwmbt_info("Firmware has already been downloaded"); 405 return 0; 406 } 407 408 firmware_path = iwmbt_get_fwname(&ver, NULL, firmware_dir, "bseq"); 409 if (firmware_path == NULL) 410 return 1; 411 iwmbt_debug("firmware_path = %s", firmware_path); 412 413 r = iwmbt_fw_read(&fw, firmware_path); 414 free(firmware_path); 415 if (r <= 0) { 416 iwmbt_debug("iwmbt_fw_read() failed"); 417 return 1; 418 } 419 420 r = iwmbt_enter_manufacturer(hdl); 421 if (r < 0) { 422 iwmbt_debug("iwmbt_enter_manufacturer() failed code %d", r); 423 iwmbt_fw_free(&fw); 424 return 1; 425 } 426 427 /* Download firmware */ 428 r = iwmbt_patch_fwfile(hdl, &fw); 429 iwmbt_fw_free(&fw); 430 if (r < 0) { 431 iwmbt_debug("Loading firmware file failed"); 432 (void)iwmbt_exit_manufacturer(hdl, IWMBT_MM_EXIT_COLD_RESET); 433 return 1; 434 } 435 436 iwmbt_info("Firmware download complete"); 437 438 r = iwmbt_exit_manufacturer(hdl, 439 (r == 0 ? IWMBT_MM_EXIT_ONLY : IWMBT_MM_EXIT_WARM_RESET)); 440 if (r < 0) { 441 iwmbt_debug("iwmbt_exit_manufacturer() failed code %d", r); 442 return 1; 443 } 444 445 /* Once device is running in operational mode we can ignore failures */ 446 447 /* Dump actual controller version */ 448 r = iwmbt_get_version(hdl, &ver); 449 if (r == 0) 450 iwmbt_dump_version(&ver); 451 452 if (iwmbt_enter_manufacturer(hdl) < 0) 453 return 0; 454 r = iwmbt_set_event_mask(hdl); 455 if (r == 0) 456 iwmbt_info("Intel Event Mask is set"); 457 (void)iwmbt_exit_manufacturer(hdl, IWMBT_MM_EXIT_ONLY); 458 459 return 0; 460 } 461 462 463 /* 464 * Returns 0 on success. 465 */ 466 static int 467 handle_8260(libusb_device_handle *hdl, char *firmware_dir) 468 { 469 int r; 470 uint32_t boot_param; 471 struct iwmbt_version ver; 472 struct iwmbt_boot_params params; 473 char *firmware_path = NULL; 474 475 r = iwmbt_get_version(hdl, &ver); 476 if (r < 0) { 477 iwmbt_debug("iwmbt_get_version() failed code %d", r); 478 return 1; 479 } 480 iwmbt_dump_version(&ver); 481 iwmbt_debug("fw_variant=0x%02x", (int) ver.fw_variant); 482 483 if (ver.fw_variant == FW_VARIANT_OPERATIONAL) { 484 iwmbt_info("Firmware has already been downloaded"); 485 return 0; 486 } 487 488 if (ver.fw_variant != FW_VARIANT_BOOTLOADER){ 489 iwmbt_err("unknown fw_variant 0x%02x", (int) ver.fw_variant); 490 return 1; 491 } 492 493 /* Read Intel Secure Boot Params */ 494 r = iwmbt_get_boot_params(hdl, ¶ms); 495 if (r < 0) { 496 iwmbt_debug("iwmbt_get_boot_params() failed!"); 497 return 1; 498 } 499 iwmbt_dump_boot_params(¶ms); 500 501 /* Check if firmware fragments are ACKed with a cmd complete event */ 502 if (params.limited_cce != 0x00) { 503 iwmbt_err("Unsupported Intel firmware loading method (%u)", 504 params.limited_cce); 505 return 1; 506 } 507 508 firmware_path = iwmbt_get_fwname(&ver, ¶ms, firmware_dir, "sfi"); 509 if (firmware_path == NULL) 510 return 1; 511 iwmbt_debug("firmware_path = %s", firmware_path); 512 513 /* Download firmware and parse it for magic Intel Reset parameter */ 514 r = iwmbt_init_firmware(hdl, firmware_path, &boot_param, 0, 0); 515 free(firmware_path); 516 if (r < 0) 517 return 1; 518 519 iwmbt_info("Firmware download complete"); 520 521 r = iwmbt_intel_reset(hdl, boot_param); 522 if (r < 0) { 523 iwmbt_debug("iwmbt_intel_reset() failed!"); 524 return 1; 525 } 526 527 iwmbt_info("Firmware operational"); 528 529 /* Once device is running in operational mode we can ignore failures */ 530 531 /* Dump actual controller version */ 532 r = iwmbt_get_version(hdl, &ver); 533 if (r == 0) 534 iwmbt_dump_version(&ver); 535 536 /* Apply the device configuration (DDC) parameters */ 537 firmware_path = iwmbt_get_fwname(&ver, ¶ms, firmware_dir, "ddc"); 538 iwmbt_debug("ddc_path = %s", firmware_path); 539 if (firmware_path != NULL) { 540 r = iwmbt_init_ddc(hdl, firmware_path); 541 if (r == 0) 542 iwmbt_info("DDC download complete"); 543 free(firmware_path); 544 } 545 546 r = iwmbt_set_event_mask(hdl); 547 if (r == 0) 548 iwmbt_info("Intel Event Mask is set"); 549 550 return 0; 551 } 552 553 554 static int 555 handle_9260(libusb_device_handle *hdl, char *firmware_dir) 556 { 557 int r; 558 uint32_t boot_param; 559 struct iwmbt_version vl; 560 struct iwmbt_version_tlv vt; 561 char *firmware_path = NULL; 562 563 r = iwmbt_get_version_tlv(hdl, &vt); 564 if (r < 0) { 565 iwmbt_debug("iwmbt_get_version_tlv() failed code %d", r); 566 return 1; 567 } 568 iwmbt_dump_version_tlv(&vt); 569 iwmbt_debug("img_type=0x%02x", (int) vt.img_type); 570 571 if (vt.img_type == TLV_IMG_TYPE_OPERATIONAL) { 572 iwmbt_info("Firmware has already been downloaded"); 573 return 0; 574 } 575 576 if (vt.img_type != TLV_IMG_TYPE_BOOTLOADER) { 577 iwmbt_err("unknown img_type 0x%02x", (int) vt.img_type); 578 return 1; 579 } 580 581 /* Check if firmware fragments are ACKed with a cmd complete event */ 582 if (vt.limited_cce != 0x00) { 583 iwmbt_err("Unsupported Intel firmware loading method (%u)", 584 vt.limited_cce); 585 return 1; 586 } 587 588 /* Check if secure boot engine is supported: 1 (ECDSA) or 0 (RSA) */ 589 if (vt.sbe_type > 0x01) { 590 iwmbt_err("Unsupported secure boot engine (%u)", 591 vt.sbe_type); 592 return 1; 593 } 594 595 firmware_path = iwmbt_get_fwname_tlv(&vt, firmware_dir, "sfi"); 596 if (firmware_path == NULL) 597 return 1; 598 iwmbt_debug("firmware_path = %s", firmware_path); 599 600 /* Download firmware and parse it for magic Intel Reset parameter */ 601 r = iwmbt_init_firmware(hdl, firmware_path, &boot_param, 602 vt.cnvi_bt >> 16 & 0x3f, vt.sbe_type); 603 free(firmware_path); 604 if (r < 0) 605 return 1; 606 607 iwmbt_info("Firmware download complete"); 608 609 r = iwmbt_intel_reset(hdl, boot_param); 610 if (r < 0) { 611 iwmbt_debug("iwmbt_intel_reset() failed!"); 612 return 1; 613 } 614 615 iwmbt_info("Firmware operational"); 616 617 /* Once device is running in operational mode we can ignore failures */ 618 619 r = iwmbt_get_version(hdl, &vl); 620 if (r == 0) 621 iwmbt_dump_version(&vl); 622 623 /* Apply the device configuration (DDC) parameters */ 624 firmware_path = iwmbt_get_fwname_tlv(&vt, firmware_dir, "ddc"); 625 iwmbt_debug("ddc_path = %s", firmware_path); 626 if (firmware_path != NULL) { 627 r = iwmbt_init_ddc(hdl, firmware_path); 628 if (r == 0) 629 iwmbt_info("DDC download complete"); 630 free(firmware_path); 631 } 632 633 r = iwmbt_set_event_mask(hdl); 634 if (r == 0) 635 iwmbt_info("Intel Event Mask is set"); 636 637 return 0; 638 } 639 640 641 int 642 main(int argc, char *argv[]) 643 { 644 libusb_context *ctx = NULL; 645 libusb_device *dev = NULL; 646 libusb_device_handle *hdl = NULL; 647 int r; 648 uint8_t bus_id = 0, dev_id = 0; 649 int devid_set = 0; 650 int n; 651 char *firmware_dir = NULL; 652 int retcode = 1; 653 enum iwmbt_device iwmbt_device; 654 655 /* Parse command line arguments */ 656 while ((n = getopt(argc, argv, "Dd:f:hI")) != -1) { 657 switch (n) { 658 case 'd': /* ugen device name */ 659 devid_set = 1; 660 if (parse_ugen_name(optarg, &bus_id, &dev_id) < 0) 661 usage(); 662 break; 663 case 'D': 664 iwmbt_do_debug = 1; 665 break; 666 case 'f': /* firmware dir */ 667 if (firmware_dir) 668 free(firmware_dir); 669 firmware_dir = strdup(optarg); 670 break; 671 case 'I': 672 iwmbt_do_info = 1; 673 break; 674 case 'h': 675 default: 676 usage(); 677 break; 678 /* NOT REACHED */ 679 } 680 } 681 682 /* Ensure the devid was given! */ 683 if (devid_set == 0) { 684 usage(); 685 /* NOTREACHED */ 686 } 687 688 /* Default the firmware path */ 689 if (firmware_dir == NULL) 690 firmware_dir = strdup(_DEFAULT_IWMBT_FIRMWARE_PATH); 691 692 /* libusb setup */ 693 r = libusb_init(&ctx); 694 if (r != 0) { 695 iwmbt_err("libusb_init failed: code %d", r); 696 exit(127); 697 } 698 699 iwmbt_debug("opening dev %d.%d", (int) bus_id, (int) dev_id); 700 701 /* Find a device based on the bus/dev id */ 702 dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_device); 703 if (dev == NULL) { 704 iwmbt_err("device not found"); 705 goto shutdown; 706 } 707 708 /* XXX enforce that bInterfaceNumber is 0 */ 709 710 /* XXX enforce the device/product id if they're non-zero */ 711 712 /* Grab device handle */ 713 r = libusb_open(dev, &hdl); 714 if (r != 0) { 715 iwmbt_err("libusb_open() failed: code %d", r); 716 goto shutdown; 717 } 718 719 /* Check if ng_ubt is attached */ 720 r = libusb_kernel_driver_active(hdl, 0); 721 if (r < 0) { 722 iwmbt_err("libusb_kernel_driver_active() failed: code %d", r); 723 goto shutdown; 724 } 725 if (r > 0) { 726 iwmbt_info("Firmware has already been downloaded"); 727 retcode = 0; 728 goto shutdown; 729 } 730 731 switch(iwmbt_device) { 732 case IWMBT_DEVICE_7260: 733 retcode = handle_7260(hdl, firmware_dir); 734 break; 735 case IWMBT_DEVICE_8260: 736 retcode = handle_8260(hdl, firmware_dir); 737 break; 738 case IWMBT_DEVICE_9260: 739 retcode = handle_9260(hdl, firmware_dir); 740 break; 741 default: 742 iwmbt_err("FIXME: unknown iwmbt type %d", (int)iwmbt_device); 743 retcode = 1; 744 } 745 746 if (retcode == 0) { 747 /* Ask kernel driver to probe and attach device again */ 748 r = libusb_reset_device(hdl); 749 if (r != 0) 750 iwmbt_err("libusb_reset_device() failed: %s", 751 libusb_strerror(r)); 752 } 753 754 shutdown: 755 if (hdl != NULL) 756 libusb_close(hdl); 757 758 if (dev != NULL) 759 libusb_unref_device(dev); 760 761 if (ctx != NULL) 762 libusb_exit(ctx); 763 764 if (retcode == 0) 765 iwmbt_info("Firmware download is successful!"); 766 else 767 iwmbt_err("Firmware download failed!"); 768 769 return (retcode); 770 } 771