2 * Copyright © 2001 Stephen Williams (steve@icarus.com)
3 * Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net)
4 * Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net)
5 * Copyright © 2012 Pete Batard (pete@akeo.ie)
6 * Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
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)
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.
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
29 #include <sys/types.h>
35 #if !defined(_WIN32) || defined(__CYGWIN__ )
37 static bool dosyslog
= false;
39 #define _stricmp strcasecmp
42 #ifndef FXLOAD_VERSION
43 #define FXLOAD_VERSION (__DATE__ " (libusbx)")
47 #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
50 void logerror(const char *format
, ...)
51 __attribute__ ((format (__printf__
, 1, 2)));
53 void logerror(const char *format
, ...)
58 #if !defined(_WIN32) || defined(__CYGWIN__ )
60 vsyslog(LOG_ERR
, format
, ap
);
63 vfprintf(stderr
, format
, ap
);
67 static int print_usage(int error_code
) {
68 fprintf(stderr
, "\nUsage: fxload [-v] [-V] [-t type] [-d vid:pid] [-p bus,addr] -i firmware\n");
69 fprintf(stderr
, " -i <path> -- Firmware to upload\n");
70 fprintf(stderr
, " -t <type> -- Target type: an21, fx, fx2, fx2lp, fx3\n");
71 fprintf(stderr
, " -d <vid:pid> -- Target device, as an USB VID:PID\n");
72 fprintf(stderr
, " -p <bus,addr> -- Target device, as a libusbx bus number and device address path\n");
73 fprintf(stderr
, " -v -- Increase verbosity\n");
74 fprintf(stderr
, " -q -- Decrease verbosity (silent mode)\n");
75 fprintf(stderr
, " -V -- Print program version\n");
81 int main(int argc
, char*argv
[])
83 fx_known_device known_device
[] = FX_KNOWN_DEVICES
;
84 const char *path
[] = { NULL
, NULL
};
85 const char *device_id
= NULL
;
86 const char *device_path
= getenv("DEVICE");
87 const char *type
= NULL
;
88 const char *fx_name
[FX_TYPE_MAX
] = FX_TYPE_NAMES
;
89 const char *ext
, *img_name
[] = IMG_TYPE_NAMES
;
90 int fx_type
= FX_TYPE_UNDEFINED
, img_type
[ARRAYSIZE(path
)];
91 int i
, j
, opt
, status
;
92 unsigned vid
= 0, pid
= 0;
93 unsigned busnum
= 0, devaddr
= 0, _busnum
, _devaddr
;
94 libusb_device
*dev
, **devs
;
95 libusb_device_handle
*device
= NULL
;
96 struct libusb_device_descriptor desc
;
98 while ((opt
= getopt(argc
, argv
, "qvV?hd:p:i:I:t:")) != EOF
)
103 if (sscanf(device_id
, "%x:%x" , &vid
, &pid
) != 2 ) {
104 fputs ("please specify VID & PID as \"vid:pid\" in hexadecimal format\n", stderr
);
110 device_path
= optarg
;
111 if (sscanf(device_path
, "%u,%u", &busnum
, &devaddr
) != 2 ) {
112 fputs ("please specify bus number & device number as \"bus,dev\" in decimal format\n", stderr
);
119 path
[FIRMWARE
] = optarg
;
123 puts(FXLOAD_VERSION
);
141 return print_usage(-1);
145 if (path
[FIRMWARE
] == NULL
) {
146 logerror("no firmware specified!\n");
147 return print_usage(-1);
149 if ((device_id
!= NULL
) && (device_path
!= NULL
)) {
150 logerror("only one of -d or -a can be specified\n");
151 return print_usage(-1);
154 /* determine the target type */
156 for (i
=0; i
<FX_TYPE_MAX
; i
++) {
157 if (strcmp(type
, fx_name
[i
]) == 0) {
162 if (i
>= FX_TYPE_MAX
) {
163 logerror("illegal microcontroller type: %s\n", type
);
164 return print_usage(-1);
168 /* open the device using libusbx */
169 status
= libusb_init(NULL
);
171 logerror("libusb_init() failed: %s\n", libusb_error_name(status
));
174 libusb_set_debug(NULL
, verbose
);
176 /* try to pick up missing parameters from known devices */
177 if ((type
== NULL
) || (device_id
== NULL
) || (device_path
!= NULL
)) {
178 if (libusb_get_device_list(NULL
, &devs
) < 0) {
179 logerror("libusb_get_device_list() failed: %s\n", libusb_error_name(status
));
182 for (i
=0; (dev
=devs
[i
]) != NULL
; i
++) {
183 _busnum
= libusb_get_bus_number(dev
);
184 _devaddr
= libusb_get_device_address(dev
);
185 if ((type
!= NULL
) && (device_path
!= NULL
)) {
186 // if both a type and bus,addr were specified, we just need to find our match
187 if ((libusb_get_bus_number(dev
) == busnum
) && (libusb_get_device_address(dev
) == devaddr
))
190 status
= libusb_get_device_descriptor(dev
, &desc
);
193 logerror("examining %04x:%04x (%d,%d)\n",
194 desc
.idVendor
, desc
.idProduct
, _busnum
, _devaddr
);
196 for (j
=0; j
<ARRAYSIZE(known_device
); j
++) {
197 if ((desc
.idVendor
== known_device
[j
].vid
)
198 && (desc
.idProduct
== known_device
[j
].pid
)) {
199 if (// nothing was specified
200 ((type
== NULL
) && (device_id
== NULL
) && (device_path
== NULL
)) ||
201 // vid:pid was specified and we have a match
202 ((type
== NULL
) && (device_id
!= NULL
) && (vid
== desc
.idVendor
) && (pid
== desc
.idProduct
)) ||
203 // bus,addr was specified and we have a match
204 ((type
== NULL
) && (device_path
!= NULL
) && (busnum
== _busnum
) && (devaddr
== _devaddr
)) ||
205 // type was specified and we have a match
206 ((type
!= NULL
) && (device_id
== NULL
) && (device_path
== NULL
) && (fx_type
== known_device
[j
].type
)) ) {
207 fx_type
= known_device
[j
].type
;
209 pid
= desc
.idProduct
;
216 if (j
< ARRAYSIZE(known_device
)) {
218 logerror("found device '%s' [%04x:%04x] (%d,%d)\n",
219 known_device
[j
].designation
, vid
, pid
, busnum
, devaddr
);
226 libusb_free_device_list(devs
, 1);
227 logerror("could not find a known device - please specify type and/or vid:pid and/or bus,dev\n");
228 return print_usage(-1);
230 status
= libusb_open(dev
, &device
);
232 logerror("libusb_open() failed: %s\n", libusb_error_name(status
));
235 libusb_free_device_list(devs
, 1);
236 } else if (device_id
!= NULL
) {
237 device
= libusb_open_device_with_vid_pid(NULL
, (uint16_t)vid
, (uint16_t)pid
);
238 if (device
== NULL
) {
239 logerror("libusb_open() failed\n");
244 /* We need to claim the first interface */
245 libusb_set_auto_detach_kernel_driver(device
, 1);
246 status
= libusb_claim_interface(device
, 0);
247 if (status
!= LIBUSB_SUCCESS
) {
248 logerror("libusb_claim_interface failed: %s\n", libusb_error_name(status
));
253 logerror("microcontroller type: %s\n", fx_name
[fx_type
]);
255 for (i
=0; i
<ARRAYSIZE(path
); i
++) {
256 if (path
[i
] != NULL
) {
257 ext
= path
[i
] + strlen(path
[i
]) - 4;
258 if ((_stricmp(ext
, ".hex") == 0) || (strcmp(ext
, ".ihx") == 0))
259 img_type
[i
] = IMG_TYPE_HEX
;
260 else if (_stricmp(ext
, ".iic") == 0)
261 img_type
[i
] = IMG_TYPE_IIC
;
262 else if (_stricmp(ext
, ".bix") == 0)
263 img_type
[i
] = IMG_TYPE_BIX
;
264 else if (_stricmp(ext
, ".img") == 0)
265 img_type
[i
] = IMG_TYPE_IMG
;
267 logerror("%s is not a recognized image type\n", path
[i
]);
271 if (verbose
&& path
[i
] != NULL
)
272 logerror("%s: type %s\n", path
[i
], img_name
[img_type
[i
]]);
275 /* single stage, put into internal memory */
277 logerror("single stage: load on-chip memory\n");
278 status
= ezusb_load_ram(device
, path
[FIRMWARE
], fx_type
, img_type
[FIRMWARE
], 0);
280 libusb_release_interface(device
, 0);
281 libusb_close(device
);