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