1 /*- 2 * Copyright (c) 2013 Adrian Chadd <adrian@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <errno.h> 34 #include <string.h> 35 #include <err.h> 36 #include <fcntl.h> 37 #include <libgen.h> 38 #include <sys/stat.h> 39 #include <sys/param.h> 40 41 #include <libusb.h> 42 43 #include "ath3k_fw.h" 44 #include "ath3k_hw.h" 45 #include "ath3k_dbg.h" 46 47 #define _DEFAULT_ATH3K_FIRMWARE_PATH "/usr/share/firmware/ath3k/" 48 49 int ath3k_do_debug = 0; 50 int ath3k_do_info = 0; 51 52 struct ath3k_devid { 53 uint16_t product_id; 54 uint16_t vendor_id; 55 int is_3012; 56 }; 57 58 static struct ath3k_devid ath3k_list[] = { 59 60 /* Atheros AR3012 with sflash firmware*/ 61 { .vendor_id = 0x0489, .product_id = 0xe04e, .is_3012 = 1 }, 62 { .vendor_id = 0x0489, .product_id = 0xe04d, .is_3012 = 1 }, 63 { .vendor_id = 0x0489, .product_id = 0xe056, .is_3012 = 1 }, 64 { .vendor_id = 0x0489, .product_id = 0xe057, .is_3012 = 1 }, 65 { .vendor_id = 0x0489, .product_id = 0xe05f, .is_3012 = 1 }, 66 { .vendor_id = 0x04c5, .product_id = 0x1330, .is_3012 = 1 }, 67 { .vendor_id = 0x04ca, .product_id = 0x3004, .is_3012 = 1 }, 68 { .vendor_id = 0x04ca, .product_id = 0x3005, .is_3012 = 1 }, 69 { .vendor_id = 0x04ca, .product_id = 0x3006, .is_3012 = 1 }, 70 { .vendor_id = 0x04ca, .product_id = 0x3008, .is_3012 = 1 }, 71 { .vendor_id = 0x04ca, .product_id = 0x300b, .is_3012 = 1 }, 72 { .vendor_id = 0x0930, .product_id = 0x0219, .is_3012 = 1 }, 73 { .vendor_id = 0x0930, .product_id = 0x0220, .is_3012 = 1 }, 74 { .vendor_id = 0x0b05, .product_id = 0x17d0, .is_3012 = 1 }, 75 { .vendor_id = 0x0CF3, .product_id = 0x0036, .is_3012 = 1 }, 76 { .vendor_id = 0x0cf3, .product_id = 0x3004, .is_3012 = 1 }, 77 { .vendor_id = 0x0cf3, .product_id = 0x3005, .is_3012 = 1 }, 78 { .vendor_id = 0x0cf3, .product_id = 0x3008, .is_3012 = 1 }, 79 { .vendor_id = 0x0cf3, .product_id = 0x311D, .is_3012 = 1 }, 80 { .vendor_id = 0x0cf3, .product_id = 0x311E, .is_3012 = 1 }, 81 { .vendor_id = 0x0cf3, .product_id = 0x311F, .is_3012 = 1 }, 82 { .vendor_id = 0x0cf3, .product_id = 0x3121, .is_3012 = 1 }, 83 { .vendor_id = 0x0CF3, .product_id = 0x817a, .is_3012 = 1 }, 84 { .vendor_id = 0x0cf3, .product_id = 0xe004, .is_3012 = 1 }, 85 { .vendor_id = 0x0cf3, .product_id = 0xe005, .is_3012 = 1 }, 86 { .vendor_id = 0x0cf3, .product_id = 0xe003, .is_3012 = 1 }, 87 { .vendor_id = 0x13d3, .product_id = 0x3362, .is_3012 = 1 }, 88 { .vendor_id = 0x13d3, .product_id = 0x3375, .is_3012 = 1 }, 89 { .vendor_id = 0x13d3, .product_id = 0x3393, .is_3012 = 1 }, 90 { .vendor_id = 0x13d3, .product_id = 0x3402, .is_3012 = 1 }, 91 92 /* Atheros AR5BBU22 with sflash firmware */ 93 { .vendor_id = 0x0489, .product_id = 0xE036, .is_3012 = 1 }, 94 { .vendor_id = 0x0489, .product_id = 0xE03C, .is_3012 = 1 }, 95 }; 96 97 static int 98 ath3k_is_3012(struct libusb_device_descriptor *d) 99 { 100 int i; 101 102 /* Search looking for whether it's an AR3012 */ 103 for (i = 0; i < (int) nitems(ath3k_list); i++) { 104 if ((ath3k_list[i].product_id == d->idProduct) && 105 (ath3k_list[i].vendor_id == d->idVendor)) { 106 fprintf(stderr, "%s: found AR3012\n", __func__); 107 return (ath3k_list[i].is_3012); 108 } 109 } 110 111 /* Not found */ 112 return (0); 113 } 114 115 static libusb_device * 116 ath3k_find_device(libusb_context *ctx, int bus_id, int dev_id) 117 { 118 libusb_device **list, *dev = NULL, *found = NULL; 119 ssize_t cnt, i; 120 121 cnt = libusb_get_device_list(ctx, &list); 122 if (cnt < 0) { 123 ath3k_err("%s: libusb_get_device_list() failed: code %lld\n", 124 __func__, 125 (long long int) cnt); 126 return (NULL); 127 } 128 129 /* 130 * XXX TODO: match on the vendor/product id too! 131 */ 132 for (i = 0; i < cnt; i++) { 133 dev = list[i]; 134 if (bus_id == libusb_get_bus_number(dev) && 135 dev_id == libusb_get_device_address(dev)) { 136 /* 137 * Take a reference so it's not freed later on. 138 */ 139 found = libusb_ref_device(dev); 140 break; 141 } 142 } 143 144 libusb_free_device_list(list, 1); 145 return (found); 146 } 147 148 static int 149 ath3k_init_ar3012(libusb_device_handle *hdl, const char *fw_path) 150 { 151 int ret; 152 153 ret = ath3k_load_patch(hdl, fw_path); 154 if (ret < 0) { 155 ath3k_err("Loading patch file failed\n"); 156 return (ret); 157 } 158 159 ret = ath3k_load_syscfg(hdl, fw_path); 160 if (ret < 0) { 161 ath3k_err("Loading sysconfig file failed\n"); 162 return (ret); 163 } 164 165 ret = ath3k_set_normal_mode(hdl); 166 if (ret < 0) { 167 ath3k_err("Set normal mode failed\n"); 168 return (ret); 169 } 170 171 ath3k_switch_pid(hdl); 172 return (0); 173 } 174 175 static int 176 ath3k_init_firmware(libusb_device_handle *hdl, const char *file_prefix) 177 { 178 struct ath3k_firmware fw; 179 char fwname[FILENAME_MAX]; 180 int ret; 181 182 /* XXX path info? */ 183 snprintf(fwname, FILENAME_MAX, "%s/ath3k-1.fw", file_prefix); 184 185 ath3k_debug("%s: loading ath3k-1.fw\n", __func__); 186 187 /* Read in the firmware */ 188 if (ath3k_fw_read(&fw, fwname) <= 0) { 189 fprintf(stderr, "%s: ath3k_fw_read() failed\n", 190 __func__); 191 return (-1); 192 } 193 194 /* Load in the firmware */ 195 ret = ath3k_load_fwfile(hdl, &fw); 196 197 /* free it */ 198 ath3k_fw_free(&fw); 199 200 return (ret); 201 } 202 203 /* 204 * Parse ugen name and extract device's bus and address 205 */ 206 207 static int 208 parse_ugen_name(char const *ugen, uint8_t *bus, uint8_t *addr) 209 { 210 char *ep; 211 212 if (strncmp(ugen, "ugen", 4) != 0) 213 return (-1); 214 215 *bus = (uint8_t) strtoul(ugen + 4, &ep, 10); 216 if (*ep != '.') 217 return (-1); 218 219 *addr = (uint8_t) strtoul(ep + 1, &ep, 10); 220 if (*ep != '\0') 221 return (-1); 222 223 return (0); 224 } 225 226 static void 227 usage(void) 228 { 229 fprintf(stderr, 230 "Usage: ath3kfw (-D) -d ugenX.Y (-f firmware path) (-I)\n"); 231 fprintf(stderr, " -D: enable debugging\n"); 232 fprintf(stderr, " -d: device to operate upon\n"); 233 fprintf(stderr, " -f: firmware path, if not default\n"); 234 fprintf(stderr, " -I: enable informational output\n"); 235 exit(127); 236 } 237 238 int 239 main(int argc, char *argv[]) 240 { 241 struct libusb_device_descriptor d; 242 libusb_context *ctx; 243 libusb_device *dev; 244 libusb_device_handle *hdl; 245 unsigned char state; 246 struct ath3k_version ver; 247 int r; 248 uint8_t bus_id = 0, dev_id = 0; 249 int devid_set = 0; 250 int n; 251 char *firmware_path = NULL; 252 int is_3012 = 0; 253 254 /* libusb setup */ 255 r = libusb_init(&ctx); 256 if (r != 0) { 257 ath3k_err("%s: libusb_init failed: code %d\n", 258 argv[0], 259 r); 260 exit(127); 261 } 262 263 /* Enable debugging, just because */ 264 libusb_set_debug(ctx, 3); 265 266 /* Parse command line arguments */ 267 while ((n = getopt(argc, argv, "Dd:f:hIm:p:v:")) != -1) { 268 switch (n) { 269 case 'd': /* ugen device name */ 270 devid_set = 1; 271 if (parse_ugen_name(optarg, &bus_id, &dev_id) < 0) 272 usage(); 273 break; 274 case 'D': 275 ath3k_do_debug = 1; 276 break; 277 case 'f': /* firmware path */ 278 if (firmware_path) 279 free(firmware_path); 280 firmware_path = strdup(optarg); 281 break; 282 case 'I': 283 ath3k_do_info = 1; 284 break; 285 case 'h': 286 default: 287 usage(); 288 break; 289 /* NOT REACHED */ 290 } 291 } 292 293 /* Ensure the devid was given! */ 294 if (devid_set == 0) { 295 usage(); 296 /* NOTREACHED */ 297 } 298 299 ath3k_debug("%s: opening dev %d.%d\n", 300 basename(argv[0]), 301 (int) bus_id, 302 (int) dev_id); 303 304 /* Find a device based on the bus/dev id */ 305 dev = ath3k_find_device(ctx, bus_id, dev_id); 306 if (dev == NULL) { 307 ath3k_err("%s: device not found\n", __func__); 308 /* XXX cleanup? */ 309 exit(1); 310 } 311 312 /* Get the device descriptor for this device entry */ 313 r = libusb_get_device_descriptor(dev, &d); 314 if (r != 0) { 315 warn("%s: libusb_get_device_descriptor: %s\n", 316 __func__, 317 libusb_strerror(r)); 318 exit(1); 319 } 320 321 /* See if its an AR3012 */ 322 if (ath3k_is_3012(&d)) { 323 is_3012 = 1; 324 325 /* If it's bcdDevice > 1, don't attach */ 326 if (d.bcdDevice > 0x0001) { 327 ath3k_debug("%s: AR3012; bcdDevice=%d, exiting\n", 328 __func__, 329 d.bcdDevice); 330 exit(0); 331 } 332 } 333 334 /* XXX enforce that bInterfaceNumber is 0 */ 335 336 /* XXX enforce the device/product id if they're non-zero */ 337 338 /* Grab device handle */ 339 r = libusb_open(dev, &hdl); 340 if (r != 0) { 341 ath3k_err("%s: libusb_open() failed: code %d\n", __func__, r); 342 /* XXX cleanup? */ 343 exit(1); 344 } 345 346 /* 347 * Get the initial NIC state. 348 */ 349 r = ath3k_get_state(hdl, &state); 350 if (r == 0) { 351 ath3k_err("%s: ath3k_get_state() failed!\n", __func__); 352 /* XXX cleanup? */ 353 exit(1); 354 } 355 ath3k_debug("%s: state=0x%02x\n", 356 __func__, 357 (int) state); 358 359 /* And the version */ 360 r = ath3k_get_version(hdl, &ver); 361 if (r == 0) { 362 ath3k_err("%s: ath3k_get_version() failed!\n", __func__); 363 /* XXX cleanup? */ 364 exit(1); 365 } 366 ath3k_info("ROM version: %d, build version: %d, ram version: %d, " 367 "ref clock=%d\n", 368 ver.rom_version, 369 ver.build_version, 370 ver.ram_version, 371 ver.ref_clock); 372 373 /* Default the firmware path */ 374 if (firmware_path == NULL) 375 firmware_path = strdup(_DEFAULT_ATH3K_FIRMWARE_PATH); 376 377 if (is_3012) { 378 (void) ath3k_init_ar3012(hdl, firmware_path); 379 } else { 380 (void) ath3k_init_firmware(hdl, firmware_path); 381 } 382 383 /* Shutdown */ 384 libusb_close(hdl); 385 hdl = NULL; 386 387 libusb_unref_device(dev); 388 dev = NULL; 389 390 libusb_exit(ctx); 391 ctx = NULL; 392 } 393