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)
7 * This source code is free software; you can redistribute it
8 * and/or modify it in source code form under the terms of the GNU
9 * General Public License as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
24 * This program supports uploading firmware into a target USB device.
26 * -I <path> -- Upload this firmware
27 * -t <type> -- uController type: an21, fx, fx2, fx2lp
29 * -D <vid:pid> -- Use this device, instead of $DEVICE
31 * -V -- Print version ID for program
38 #include <sys/types.h>
44 #if !defined(_WIN32) || defined(__CYGWIN__ )
46 static bool dosyslog
= false;
48 #define _stricmp strcasecmp
51 #ifndef FXLOAD_VERSION
52 #define FXLOAD_VERSION (__DATE__ " (development)")
56 #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
59 void logerror(const char *format
, ...)
60 __attribute__ ((format (__printf__
, 1, 2)));
62 void logerror(const char *format
, ...)
67 #if !defined(_WIN32) || defined(__CYGWIN__ )
69 vsyslog(LOG_ERR
, format
, ap
);
72 vfprintf(stderr
, format
, ap
);
78 int main(int argc
, char*argv
[])
80 fx_known_device known_device
[] = FX_KNOWN_DEVICES
;
81 const char *path
[] = { NULL
, NULL
};
82 const char *device_id
= getenv("DEVICE");
83 const char *type
= NULL
;
84 const char *fx_name
[FX_TYPE_MAX
] = FX_TYPE_NAMES
;
85 const char *ext
, *img_name
[] = IMG_TYPE_NAMES
;
86 int fx_type
= FX_TYPE_UNDEFINED
, img_type
[ARRAYSIZE(path
)];
87 int i
, j
, opt
, status
;
88 unsigned vid
= 0, pid
= 0;
89 libusb_device
*dev
, **devs
;
90 libusb_device_handle
*device
= NULL
;
91 struct libusb_device_descriptor desc
;
93 while ((opt
= getopt(argc
, argv
, "vV?D:I:c:s:t:")) != EOF
)
101 path
[FIRMWARE
] = optarg
;
105 puts(FXLOAD_VERSION
);
122 if (path
[FIRMWARE
] == NULL
) {
123 logerror("no firmware specified!\n");
125 fprintf(stderr
, "\nusage: %s [-vV] [-t type] [-D vid:pid] -I firmware\n", argv
[0]);
126 fprintf(stderr
, " type: one of an21, fx, fx2, fx2lp\n");
130 if ((device_id
!= NULL
) && (sscanf(device_id
, "%x:%x" , &vid
, &pid
) != 2 )) {
131 fputs ("please specify VID & PID as \"vid:pid\" in hexadecimal format\n", stderr
);
135 /* determine the target type */
137 for (i
=0; i
<FX_TYPE_MAX
; i
++) {
138 if (strcmp(type
, fx_name
[i
]) == 0) {
143 if (i
>= FX_TYPE_MAX
) {
144 logerror("illegal microcontroller type: %s\n", type
);
149 /* open the device using libusbx */
150 status
= libusb_init(NULL
);
152 logerror("libusb_init() failed: %s\n", libusb_error_name(status
));
155 libusb_set_debug(NULL
, verbose
);
157 /* try to pick up missing parameters from known devices */
158 if ((type
== NULL
) || (device_id
== NULL
)) {
159 if (libusb_get_device_list(NULL
, &devs
) < 0) {
160 logerror("libusb_get_device_list() failed: %s\n", libusb_error_name(status
));
163 for (i
=0; (dev
=devs
[i
]) != NULL
; i
++) {
164 status
= libusb_get_device_descriptor(dev
, &desc
);
167 logerror("trying to match against %04x:%04x\n", desc
.idVendor
, desc
.idProduct
);
168 for (j
=0; j
<ARRAYSIZE(known_device
); j
++) {
169 if ((desc
.idVendor
== known_device
[j
].vid
)
170 && (desc
.idProduct
== known_device
[j
].pid
)) {
171 if ((type
== NULL
) && (device_id
== NULL
)) {
172 fx_type
= known_device
[j
].type
;
174 pid
= desc
.idProduct
;
176 } else if ((type
== NULL
) && (vid
== desc
.idVendor
)
177 && (pid
== desc
.idProduct
)) {
178 fx_type
= known_device
[j
].type
;
180 } else if ((device_id
== NULL
)
181 && (fx_type
== known_device
[j
].type
)) {
183 pid
= desc
.idProduct
;
188 if (j
< ARRAYSIZE(known_device
)) {
190 logerror("found device '%s' [%04x:%04x]\n",
191 known_device
[j
].designation
, vid
, pid
);
197 libusb_free_device_list(devs
, 1);
198 logerror("could not find a known device - please specify type and/or vid:pid\n");
201 status
= libusb_open(dev
, &device
);
203 logerror("libusb_open() failed: %s\n", libusb_error_name(status
));
206 libusb_free_device_list(devs
, 1);
208 device
= libusb_open_device_with_vid_pid(NULL
, (uint16_t)vid
, (uint16_t)pid
);
209 if (device
== NULL
) {
210 logerror("libusb_open() failed\n");
214 /* We need to claim the first interface */
215 status
= libusb_claim_interface(device
, 0);
216 #if defined(__linux__)
217 if (status
!= LIBUSB_SUCCESS
) {
218 /* Maybe we need to detach the driver */
219 libusb_detach_kernel_driver(device
, 0);
220 status
= libusb_claim_interface(device
, 0);
223 if (status
!= LIBUSB_SUCCESS
) {
224 logerror("libusb_claim_interface failed: %s\n", libusb_error_name(status
));
229 logerror("microcontroller type: %s\n", fx_name
[fx_type
]);
231 for (i
=0; i
<ARRAYSIZE(path
); i
++) {
232 if (path
[i
] != NULL
) {
233 ext
= path
[i
] + strlen(path
[i
]) - 4;
234 if ((_stricmp(ext
, ".hex") == 0) || (strcmp(ext
, ".ihx") == 0))
235 img_type
[i
] = IMG_TYPE_HEX
;
236 else if (_stricmp(ext
, ".iic") == 0)
237 img_type
[i
] = IMG_TYPE_IIC
;
238 else if (_stricmp(ext
, ".bix") == 0)
239 img_type
[i
] = IMG_TYPE_BIX
;
241 logerror("%s is not a recognized image type\n", path
[i
]);
245 if (verbose
&& path
[i
] != NULL
)
246 logerror("%s: type %s\n", path
[i
], img_name
[img_type
[i
]]);
249 /* single stage, put into internal memory */
251 logerror("single stage: load on-chip memory\n");
252 status
= ezusb_load_ram(device
, path
[FIRMWARE
], fx_type
, img_type
[FIRMWARE
], 0);
254 libusb_release_interface(device
, 0);
255 libusb_close(device
);