1 /* 2 * Copyright 2001 Stephen Williams (steve (at) icarus.com) 3 * Copyright 2001-2002 David Brownell (dbrownell (at) users.sourceforge.net) 4 * Copyright 2008 Roger Williams (rawqux (at) users.sourceforge.net) 5 * Copyright 2012 Pete Batard (pete (at) akeo.ie) 6 * Copyright 2013 Federico Manzan (f.manzan (at) gmail.com) 7 * 8 * This source code is free software; you can redistribute it 9 * and/or modify it in source code form under the terms of the GNU 10 * General Public License as published by the Free Software 11 * Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 22 */ 23 24 #include <stdlib.h> 25 #include <stdio.h> 26 #include <string.h> 27 #include <stdint.h> 28 #include <stdarg.h> 29 #include <sys/types.h> 30 #include <getopt.h> 31 32 #include "libusb.h" 33 #include "ezusb.h" 34 35 #if !defined(_WIN32) || defined(__CYGWIN__ ) 36 #include <syslog.h> 37 static bool dosyslog = false; 38 #include <strings.h> 39 #define _stricmp strcasecmp 40 #endif 41 42 #ifndef FXLOAD_VERSION 43 #define FXLOAD_VERSION (__DATE__ " (libusb)") 44 #endif 45 46 #ifndef ARRAYSIZE 47 #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) 48 #endif 49 50 void logerror(const char *format, ...) 51 __attribute__ ((format (__printf__, 1, 2))); 52 53 void logerror(const char *format, ...) 54 { 55 va_list ap; 56 va_start(ap, format); 57 58 #if !defined(_WIN32) || defined(__CYGWIN__ ) 59 if (dosyslog) 60 vsyslog(LOG_ERR, format, ap); 61 else 62 #endif 63 vfprintf(stderr, format, ap); 64 va_end(ap); 65 } 66 67 static int print_usage(int error_code) { 68 fprintf(stderr, "\nUsage: fxload [-v] [-V] [-t type] [-d vid:pid] [-p bus,addr] [-s loader] -i firmware\n"); 69 fprintf(stderr, " -i <path> -- Firmware to upload\n"); 70 fprintf(stderr, " -s <path> -- Second stage loader\n"); 71 fprintf(stderr, " -t <type> -- Target type: an21, fx, fx2, fx2lp, fx3\n"); 72 fprintf(stderr, " -d <vid:pid> -- Target device, as an USB VID:PID\n"); 73 fprintf(stderr, " -p <bus,addr> -- Target device, as a libusb bus number and device address path\n"); 74 fprintf(stderr, " -v -- Increase verbosity\n"); 75 fprintf(stderr, " -q -- Decrease verbosity (silent mode)\n"); 76 fprintf(stderr, " -V -- Print program version\n"); 77 return error_code; 78 } 79 80 #define FIRMWARE 0 81 #define LOADER 1 82 int main(int argc, char*argv[]) 83 { 84 fx_known_device known_device[] = FX_KNOWN_DEVICES; 85 const char *path[] = { NULL, NULL }; 86 const char *device_id = NULL; 87 const char *device_path = getenv("DEVICE"); 88 const char *type = NULL; 89 const char *fx_name[FX_TYPE_MAX] = FX_TYPE_NAMES; 90 const char *ext, *img_name[] = IMG_TYPE_NAMES; 91 int fx_type = FX_TYPE_UNDEFINED, img_type[ARRAYSIZE(path)]; 92 int opt, status; 93 unsigned int i, j; 94 unsigned vid = 0, pid = 0; 95 unsigned busnum = 0, devaddr = 0, _busnum, _devaddr; 96 libusb_device *dev, **devs; 97 libusb_device_handle *device = NULL; 98 struct libusb_device_descriptor desc; 99 100 while ((opt = getopt(argc, argv, "qvV?hd:p:i:I:s:S:t:")) != EOF) 101 switch (opt) { 102 103 case 'd': 104 device_id = optarg; 105 if (sscanf(device_id, "%x:%x" , &vid, &pid) != 2 ) { 106 fputs ("please specify VID & PID as \"vid:pid\" in hexadecimal format\n", stderr); 107 return -1; 108 } 109 break; 110 111 case 'p': 112 device_path = optarg; 113 if (sscanf(device_path, "%u,%u", &busnum, &devaddr) != 2 ) { 114 fputs ("please specify bus number & device number as \"bus,dev\" in decimal format\n", stderr); 115 return -1; 116 } 117 break; 118 119 case 'i': 120 case 'I': 121 path[FIRMWARE] = optarg; 122 break; 123 124 case 's': 125 case 'S': 126 path[LOADER] = optarg; 127 break; 128 129 case 'V': 130 puts(FXLOAD_VERSION); 131 return 0; 132 133 case 't': 134 type = optarg; 135 break; 136 137 case 'v': 138 verbose++; 139 break; 140 141 case 'q': 142 verbose--; 143 break; 144 145 case '?': 146 case 'h': 147 default: 148 return print_usage(-1); 149 150 } 151 152 if (path[FIRMWARE] == NULL) { 153 logerror("no firmware specified!\n"); 154 return print_usage(-1); 155 } 156 if ((device_id != NULL) && (device_path != NULL)) { 157 logerror("only one of -d or -p can be specified\n"); 158 return print_usage(-1); 159 } 160 161 /* determine the target type */ 162 if (type != NULL) { 163 for (i=0; i<FX_TYPE_MAX; i++) { 164 if (strcmp(type, fx_name[i]) == 0) { 165 fx_type = i; 166 break; 167 } 168 } 169 if (i >= FX_TYPE_MAX) { 170 logerror("illegal microcontroller type: %s\n", type); 171 return print_usage(-1); 172 } 173 } 174 175 /* open the device using libusb */ 176 status = libusb_init(NULL); 177 if (status < 0) { 178 logerror("libusb_init() failed: %s\n", libusb_error_name(status)); 179 return -1; 180 } 181 libusb_set_debug(NULL, verbose); 182 183 /* try to pick up missing parameters from known devices */ 184 if ((type == NULL) || (device_id == NULL) || (device_path != NULL)) { 185 if (libusb_get_device_list(NULL, &devs) < 0) { 186 logerror("libusb_get_device_list() failed: %s\n", libusb_error_name(status)); 187 goto err; 188 } 189 for (i=0; (dev=devs[i]) != NULL; i++) { 190 _busnum = libusb_get_bus_number(dev); 191 _devaddr = libusb_get_device_address(dev); 192 if ((type != NULL) && (device_path != NULL)) { 193 // if both a type and bus,addr were specified, we just need to find our match 194 if ((libusb_get_bus_number(dev) == busnum) && (libusb_get_device_address(dev) == devaddr)) 195 break; 196 } else { 197 status = libusb_get_device_descriptor(dev, &desc); 198 if (status >= 0) { 199 if (verbose >= 3) { 200 logerror("examining %04x:%04x (%d,%d)\n", 201 desc.idVendor, desc.idProduct, _busnum, _devaddr); 202 } 203 for (j=0; j<ARRAYSIZE(known_device); j++) { 204 if ((desc.idVendor == known_device[j].vid) 205 && (desc.idProduct == known_device[j].pid)) { 206 if (// nothing was specified 207 ((type == NULL) && (device_id == NULL) && (device_path == NULL)) || 208 // vid:pid was specified and we have a match 209 ((type == NULL) && (device_id != NULL) && (vid == desc.idVendor) && (pid == desc.idProduct)) || 210 // bus,addr was specified and we have a match 211 ((type == NULL) && (device_path != NULL) && (busnum == _busnum) && (devaddr == _devaddr)) || 212 // type was specified and we have a match 213 ((type != NULL) && (device_id == NULL) && (device_path == NULL) && (fx_type == known_device[j].type)) ) { 214 fx_type = known_device[j].type; 215 vid = desc.idVendor; 216 pid = desc.idProduct; 217 busnum = _busnum; 218 devaddr = _devaddr; 219 break; 220 } 221 } 222 } 223 if (j < ARRAYSIZE(known_device)) { 224 if (verbose) 225 logerror("found device '%s' [%04x:%04x] (%d,%d)\n", 226 known_device[j].designation, vid, pid, busnum, devaddr); 227 break; 228 } 229 } 230 } 231 } 232 if (dev == NULL) { 233 libusb_free_device_list(devs, 1); 234 libusb_exit(NULL); 235 logerror("could not find a known device - please specify type and/or vid:pid and/or bus,dev\n"); 236 return print_usage(-1); 237 } 238 status = libusb_open(dev, &device); 239 libusb_free_device_list(devs, 1); 240 if (status < 0) { 241 logerror("libusb_open() failed: %s\n", libusb_error_name(status)); 242 goto err; 243 } 244 } else if (device_id != NULL) { 245 device = libusb_open_device_with_vid_pid(NULL, (uint16_t)vid, (uint16_t)pid); 246 if (device == NULL) { 247 logerror("libusb_open() failed\n"); 248 goto err; 249 } 250 } 251 252 /* We need to claim the first interface */ 253 libusb_set_auto_detach_kernel_driver(device, 1); 254 status = libusb_claim_interface(device, 0); 255 if (status != LIBUSB_SUCCESS) { 256 libusb_close(device); 257 logerror("libusb_claim_interface failed: %s\n", libusb_error_name(status)); 258 goto err; 259 } 260 261 if (verbose) 262 logerror("microcontroller type: %s\n", fx_name[fx_type]); 263 264 for (i=0; i<ARRAYSIZE(path); i++) { 265 if (path[i] != NULL) { 266 ext = path[i] + strlen(path[i]) - 4; 267 if ((_stricmp(ext, ".hex") == 0) || (strcmp(ext, ".ihx") == 0)) 268 img_type[i] = IMG_TYPE_HEX; 269 else if (_stricmp(ext, ".iic") == 0) 270 img_type[i] = IMG_TYPE_IIC; 271 else if (_stricmp(ext, ".bix") == 0) 272 img_type[i] = IMG_TYPE_BIX; 273 else if (_stricmp(ext, ".img") == 0) 274 img_type[i] = IMG_TYPE_IMG; 275 else { 276 logerror("%s is not a recognized image type\n", path[i]); 277 goto err; 278 } 279 } 280 if (verbose && path[i] != NULL) 281 logerror("%s: type %s\n", path[i], img_name[img_type[i]]); 282 } 283 284 if (path[LOADER] == NULL) { 285 /* single stage, put into internal memory */ 286 if (verbose > 1) 287 logerror("single stage: load on-chip memory\n"); 288 status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 0); 289 } else { 290 /* two-stage, put loader into internal memory */ 291 if (verbose > 1) 292 logerror("1st stage: load 2nd stage loader\n"); 293 status = ezusb_load_ram(device, path[LOADER], fx_type, img_type[LOADER], 0); 294 if (status == 0) { 295 /* two-stage, put firmware into internal memory */ 296 if (verbose > 1) 297 logerror("2nd state: load on-chip memory\n"); 298 status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 1); 299 } 300 } 301 302 libusb_release_interface(device, 0); 303 libusb_close(device); 304 libusb_exit(NULL); 305 return status; 306 err: 307 libusb_exit(NULL); 308 return -1; 309 } 310