diff options
Diffstat (limited to 'utils/jz4740_tools/jz4740_usbtool.c')
-rwxr-xr-x | utils/jz4740_tools/jz4740_usbtool.c | 732 |
1 files changed, 732 insertions, 0 deletions
diff --git a/utils/jz4740_tools/jz4740_usbtool.c b/utils/jz4740_tools/jz4740_usbtool.c new file mode 100755 index 0000000000..4437f63675 --- /dev/null +++ b/utils/jz4740_tools/jz4740_usbtool.c | |||
@@ -0,0 +1,732 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * based on tcctool.c by Dave Chapman | ||
13 | * | ||
14 | * USB code based on ifp-line - http://ifp-driver.sourceforge.net | ||
15 | * | ||
16 | * ifp-line is (C) Pavel Kriz, Jun Yamishiro and Joe Roback and | ||
17 | * licensed under the GPL (v2) | ||
18 | * | ||
19 | * | ||
20 | * All files in this archive are subject to the GNU General Public License. | ||
21 | * See the file COPYING in the source tree root for full license agreement. | ||
22 | * | ||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
24 | * KIND, either express or implied. | ||
25 | * | ||
26 | ****************************************************************************/ | ||
27 | |||
28 | #include <stdio.h> | ||
29 | #include <inttypes.h> | ||
30 | #include <usb.h> | ||
31 | #include <string.h> | ||
32 | #include <sys/types.h> | ||
33 | #include <sys/stat.h> | ||
34 | #include <unistd.h> | ||
35 | #include <fcntl.h> | ||
36 | #include "jz4740.h" | ||
37 | #include <stdbool.h> | ||
38 | #include <unistd.h> | ||
39 | |||
40 | #define VERSION "0.3" | ||
41 | |||
42 | #define MAX_FIRMWARESIZE (64*1024*1024) /* Arbitrary limit (for safety) */ | ||
43 | |||
44 | /* For win32 compatibility: */ | ||
45 | #ifndef O_BINARY | ||
46 | #define O_BINARY 0 | ||
47 | #endif | ||
48 | |||
49 | /* USB IDs for USB Boot Mode */ | ||
50 | #define VID 0x601A | ||
51 | #define PID 0x4740 | ||
52 | |||
53 | #define EP_BULK_TO 0x01 | ||
54 | #define TOUT 5000 | ||
55 | |||
56 | enum USB_JZ4740_REQUEST | ||
57 | { | ||
58 | VR_GET_CPU_INFO = 0, | ||
59 | VR_SET_DATA_ADDRESS, | ||
60 | VR_SET_DATA_LENGTH, | ||
61 | VR_FLUSH_CACHES, | ||
62 | VR_PROGRAM_START1, | ||
63 | VR_PROGRAM_START2, | ||
64 | VR_NOR_OPS, | ||
65 | VR_NAND_OPS, | ||
66 | VR_SDRAM_OPS, | ||
67 | VR_CONFIGURATION | ||
68 | }; | ||
69 | |||
70 | enum NOR_OPS_TYPE | ||
71 | { | ||
72 | NOR_INIT = 0, | ||
73 | NOR_QUERY, | ||
74 | NOR_WRITE, | ||
75 | NOR_ERASE_CHIP, | ||
76 | NOR_ERASE_SECTOR | ||
77 | }; | ||
78 | |||
79 | enum NOR_FLASH_TYPE | ||
80 | { | ||
81 | NOR_AM29 = 0, | ||
82 | NOR_SST28, | ||
83 | NOR_SST39x16, | ||
84 | NOR_SST39x8 | ||
85 | }; | ||
86 | |||
87 | enum NAND_OPS_TYPE | ||
88 | { | ||
89 | NAND_QUERY = 0, | ||
90 | NAND_INIT, | ||
91 | NAND_MARK_BAD, | ||
92 | NAND_READ_OOB, | ||
93 | NAND_READ_RAW, | ||
94 | NAND_ERASE, | ||
95 | NAND_READ, | ||
96 | NAND_PROGRAM, | ||
97 | NAND_READ_TO_RAM | ||
98 | }; | ||
99 | |||
100 | enum SDRAM_OPS_TYPE | ||
101 | { | ||
102 | SDRAM_LOAD, | ||
103 | |||
104 | }; | ||
105 | |||
106 | enum DATA_STRUCTURE_OB | ||
107 | { | ||
108 | DS_flash_info , | ||
109 | DS_hand | ||
110 | }; | ||
111 | |||
112 | enum OPTION | ||
113 | { | ||
114 | OOB_ECC, | ||
115 | OOB_NO_ECC, | ||
116 | NO_OOB, | ||
117 | }; | ||
118 | |||
119 | int filesize(FILE* fd) | ||
120 | { | ||
121 | int tmp; | ||
122 | fseek(fd, 0, SEEK_END); | ||
123 | tmp = ftell(fd); | ||
124 | fseek(fd, 0, SEEK_SET); | ||
125 | return tmp; | ||
126 | } | ||
127 | |||
128 | #define SEND_COMMAND(cmd, arg) err = usb_control_msg(dh, USB_ENDPOINT_OUT | USB_TYPE_VENDOR, cmd, arg>>16, arg&0xFFFF, NULL, 0, TOUT);\ | ||
129 | if (err < 0) \ | ||
130 | { \ | ||
131 | fprintf(stderr,"\n[ERR] Error sending control message (%d, %s)\n", err, usb_strerror()); \ | ||
132 | return -1; \ | ||
133 | } | ||
134 | |||
135 | #define GET_CPU_INFO(s) err = usb_control_msg(dh, USB_ENDPOINT_IN | USB_TYPE_VENDOR, VR_GET_CPU_INFO, 0, 0, s, 8, TOUT); \ | ||
136 | if (err < 0) \ | ||
137 | { \ | ||
138 | fprintf(stderr,"\n[ERR] Error sending control message (%d, %s)\n", err, usb_strerror()); \ | ||
139 | return -1; \ | ||
140 | } | ||
141 | |||
142 | #define SEND_DATA(ptr, size) err = usb_bulk_write(dh, USB_ENDPOINT_OUT | EP_BULK_TO, ptr, size, TOUT); \ | ||
143 | if (err != size) \ | ||
144 | { \ | ||
145 | fprintf(stderr,"\n[ERR] Error writing data\n"); \ | ||
146 | fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); \ | ||
147 | return -1; \ | ||
148 | } | ||
149 | |||
150 | #define GET_DATA(ptr, size) err = usb_bulk_read(dh, USB_ENDPOINT_IN | EP_BULK_TO, ptr, size, TOUT); \ | ||
151 | if (err != size) \ | ||
152 | { \ | ||
153 | fprintf(stderr,"\n[ERR] Error writing data\n"); \ | ||
154 | fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); \ | ||
155 | return -1; \ | ||
156 | } | ||
157 | |||
158 | int upload_app(usb_dev_handle* dh, int address, unsigned char* p, int len, bool stage2) | ||
159 | { | ||
160 | int err; | ||
161 | char buf[8]; | ||
162 | unsigned char* tmp_buf; | ||
163 | |||
164 | fprintf(stderr, "[INFO] GET_CPU_INFO: "); | ||
165 | GET_CPU_INFO(buf); | ||
166 | buf[8] = 0; | ||
167 | fprintf(stderr, "%s\n", buf); | ||
168 | #if 0 | ||
169 | fprintf(stderr, "[INFO] Flushing cache..."); | ||
170 | SEND_COMMAND(VR_FLUSH_CACHES, 0); | ||
171 | fprintf(stderr, " Done!\n"); | ||
172 | #endif | ||
173 | |||
174 | fprintf(stderr, "[INFO] SET_DATA_ADDRESS to 0x%x...", address); | ||
175 | SEND_COMMAND(VR_SET_DATA_ADDRESS, address); | ||
176 | fprintf(stderr, " Done!\n"); | ||
177 | |||
178 | fprintf(stderr, "[INFO] Sending data..."); | ||
179 | /* Must not split the file in several packages! */ | ||
180 | SEND_DATA(p, len); | ||
181 | fprintf(stderr, " Done!\n"); | ||
182 | |||
183 | fprintf(stderr, "[INFO] Verifying data..."); | ||
184 | SEND_COMMAND(VR_SET_DATA_ADDRESS, address); | ||
185 | SEND_COMMAND(VR_SET_DATA_LENGTH, len); | ||
186 | tmp_buf = malloc(len); | ||
187 | if (tmp_buf == NULL) | ||
188 | { | ||
189 | fprintf(stderr, "\n[ERR] Could not allocate memory.\n"); | ||
190 | return -1; | ||
191 | } | ||
192 | GET_DATA(tmp_buf, len); | ||
193 | if (memcmp(tmp_buf, p, len) != 0) | ||
194 | fprintf(stderr, "\n[WARN] Sent data isn't the same as received data...\n"); | ||
195 | else | ||
196 | fprintf(stderr, " Done!\n"); | ||
197 | free(tmp_buf); | ||
198 | |||
199 | fprintf(stderr, "[INFO] Booting device [STAGE%d]...", (stage2 ? 2 : 1)); | ||
200 | SEND_COMMAND((stage2 ? VR_PROGRAM_START2 : VR_PROGRAM_START1), (address+(stage2 ? 8 : 0)) ); | ||
201 | fprintf(stderr, " Done!\n"); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | int read_data(usb_dev_handle* dh, int address, unsigned char *p, int len) | ||
207 | { | ||
208 | int err; | ||
209 | char buf[8]; | ||
210 | |||
211 | fprintf(stderr, "[INFO] GET_CPU_INFO: "); | ||
212 | GET_CPU_INFO(buf); | ||
213 | buf[8] = 0; | ||
214 | fprintf(stderr, "%s\n", buf); | ||
215 | |||
216 | fprintf(stderr, "[INFO] Reading data..."); | ||
217 | SEND_COMMAND(VR_SET_DATA_ADDRESS, address); | ||
218 | SEND_COMMAND(VR_SET_DATA_LENGTH, len); | ||
219 | GET_DATA(p, len); | ||
220 | fprintf(stderr, " Done!\n"); | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | unsigned int read_reg(usb_dev_handle* dh, int address, int size) | ||
225 | { | ||
226 | int err; | ||
227 | unsigned char buf[4]; | ||
228 | |||
229 | SEND_COMMAND(VR_SET_DATA_ADDRESS, address); | ||
230 | SEND_COMMAND(VR_SET_DATA_LENGTH, size); | ||
231 | GET_DATA(buf, size); | ||
232 | |||
233 | if(size == 1) | ||
234 | return buf[0]; | ||
235 | else if(size == 2) | ||
236 | return (buf[1] << 8) | buf[0]; | ||
237 | else if(size == 4) | ||
238 | return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; | ||
239 | else | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | int set_reg(usb_dev_handle* dh, int address, unsigned int val, int size) | ||
244 | { | ||
245 | int err, i; | ||
246 | unsigned char buf[4]; | ||
247 | |||
248 | buf[0] = val & 0xff; | ||
249 | if(i > 1) | ||
250 | { | ||
251 | buf[1] = (val >> 8) & 0xff; | ||
252 | if(i > 2) | ||
253 | { | ||
254 | buf[2] = (val >> 16) & 0xff; | ||
255 | buf[3] = (val >> 24) & 0xff; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | SEND_COMMAND(VR_SET_DATA_ADDRESS, address); | ||
260 | SEND_DATA(buf, size); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | #define or_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) | (val)), size); | ||
265 | #define and_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) & (val)), size); | ||
266 | #define bc_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) & ~(val)), size); | ||
267 | #define xor_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) ^ (val)), size); | ||
268 | |||
269 | #define TEST(m, size) fprintf(stderr, "%s -> %x\n", #m, read_reg(dh, m, size)); | ||
270 | int test_device(usb_dev_handle* dh) | ||
271 | { | ||
272 | TEST(INTC_ISR, 4); | ||
273 | TEST(INTC_IMR, 4); | ||
274 | TEST(INTC_IMSR, 4); | ||
275 | TEST(INTC_IMCR, 4); | ||
276 | TEST(INTC_IPR, 4); | ||
277 | |||
278 | fprintf(stderr, "\n"); | ||
279 | TEST(RTC_RCR, 4); | ||
280 | TEST(RTC_RSR, 4); | ||
281 | TEST(RTC_RSAR, 4); | ||
282 | TEST(RTC_RGR, 4); | ||
283 | TEST(RTC_HCR, 4); | ||
284 | TEST(RTC_RCR, 4); | ||
285 | TEST(RTC_HWFCR, 4); | ||
286 | TEST(RTC_HRCR, 4); | ||
287 | TEST(RTC_HWCR, 4); | ||
288 | TEST(RTC_HWSR, 4); | ||
289 | |||
290 | fprintf(stderr, "\n"); | ||
291 | TEST(GPIO_PXPIN(0), 4); | ||
292 | TEST(GPIO_PXPIN(1), 4); | ||
293 | TEST(GPIO_PXPIN(2), 4); | ||
294 | TEST(GPIO_PXPIN(3), 4); | ||
295 | |||
296 | fprintf(stderr, "\n"); | ||
297 | TEST(CPM_CLKGR, 4); | ||
298 | |||
299 | fprintf(stderr, "\n"); | ||
300 | //or_reg(dh, SADC_ENA, SADC_ENA_TSEN, 1); | ||
301 | TEST(SADC_ENA, 1); | ||
302 | TEST(SADC_CTRL, 1); | ||
303 | TEST(SADC_TSDAT, 4); | ||
304 | TEST(SADC_BATDAT, 2); | ||
305 | TEST(SADC_STATE, 1); | ||
306 | |||
307 | fprintf(stderr, "\n"); | ||
308 | |||
309 | TEST(SLCD_CFG, 4); | ||
310 | TEST(SLCD_CTRL, 1); | ||
311 | TEST(SLCD_STATE, 1); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | #define VOL_DOWN (1 << 27) | ||
317 | #define VOL_UP (1 << 0) | ||
318 | #define MENU (1 << 1) | ||
319 | #define HOLD (1 << 16) | ||
320 | #define OFF (1 << 29) | ||
321 | #define MASK (VOL_DOWN|VOL_UP|MENU|HOLD|OFF) | ||
322 | #define TS_MASK (SADC_STATE_PEND|SADC_STATE_PENU|SADC_STATE_TSRDY) | ||
323 | int probe_device(usb_dev_handle* dh) | ||
324 | { | ||
325 | int tmp; | ||
326 | |||
327 | //or_reg(dh, SADC_ENA, SADC_ENA_TSEN, 1); | ||
328 | while(1) | ||
329 | { | ||
330 | if(read_reg(dh, SADC_STATE, 1) & SADC_STATE_TSRDY) | ||
331 | { | ||
332 | printf("%x\n", read_reg(dh, SADC_TSDAT, 4)); | ||
333 | or_reg(dh, SADC_CTRL, read_reg(dh, SADC_STATE, 1) & TS_MASK, 1); | ||
334 | } | ||
335 | |||
336 | tmp = read_reg(dh, GPIO_PXPIN(3), 4); | ||
337 | if(tmp < 0) | ||
338 | return tmp; | ||
339 | if(tmp ^ MASK) | ||
340 | { | ||
341 | if(!(tmp & VOL_DOWN)) | ||
342 | printf("VOL_DOWN\t"); | ||
343 | if(!(tmp & VOL_UP)) | ||
344 | printf("VOL_UP\t"); | ||
345 | if(!(tmp & MENU)) | ||
346 | printf("MENU\t"); | ||
347 | if(!(tmp & OFF)) | ||
348 | printf("OFF\t"); | ||
349 | if(!(tmp & HOLD)) | ||
350 | printf("HOLD\t"); | ||
351 | printf("\n"); | ||
352 | } | ||
353 | } | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | unsigned int read_file(const char *name, unsigned char **buffer) | ||
358 | { | ||
359 | FILE *fd; | ||
360 | int len, n; | ||
361 | |||
362 | fd = fopen(name, "rb"); | ||
363 | if (fd < 0) | ||
364 | { | ||
365 | fprintf(stderr, "[ERR] Could not open %s\n", name); | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | len = filesize(fd); | ||
370 | |||
371 | *buffer = (unsigned char*)malloc(len); | ||
372 | if (*buffer == NULL) | ||
373 | { | ||
374 | fprintf(stderr, "[ERR] Could not allocate memory.\n"); | ||
375 | fclose(fd); | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | n = fread(*buffer, 1, len, fd); | ||
380 | if (n != len) | ||
381 | { | ||
382 | fprintf(stderr, "[ERR] Short read.\n"); | ||
383 | fclose(fd); | ||
384 | return 0; | ||
385 | } | ||
386 | fclose(fd); | ||
387 | |||
388 | return len; | ||
389 | } | ||
390 | #define _GET_CPU fprintf(stderr, "[INFO] GET_CPU_INFO:"); \ | ||
391 | GET_CPU_INFO(cpu); \ | ||
392 | cpu[8] = 0; \ | ||
393 | fprintf(stderr, " %s\n", cpu); | ||
394 | #define _SET_ADDR(a) fprintf(stderr, "[INFO] Set address to 0x%x...", a); \ | ||
395 | SEND_COMMAND(VR_SET_DATA_ADDRESS, a); \ | ||
396 | fprintf(stderr, " Done!\n"); | ||
397 | #define _SEND_FILE(a) fsize = read_file(a, &buffer); \ | ||
398 | fprintf(stderr, "[INFO] Sending file %s: %d bytes...", a, fsize); \ | ||
399 | SEND_DATA(buffer, fsize); \ | ||
400 | free(buffer); \ | ||
401 | fprintf(stderr, " Done!\n"); | ||
402 | #define _VERIFY_DATA(a,c) fprintf(stderr, "[INFO] Verifying data (%s)...", a); \ | ||
403 | fsize = read_file(a, &buffer); \ | ||
404 | buffer2 = (unsigned char*)malloc(fsize); \ | ||
405 | SEND_COMMAND(VR_SET_DATA_ADDRESS, c); \ | ||
406 | SEND_COMMAND(VR_SET_DATA_LENGTH, fsize); \ | ||
407 | GET_DATA(buffer2, fsize); \ | ||
408 | if(memcmp(buffer, buffer2, fsize) != 0) \ | ||
409 | fprintf(stderr, "\n[WARN] Sent data isn't the same as received data...\n"); \ | ||
410 | else \ | ||
411 | fprintf(stderr, " Done!\n"); \ | ||
412 | free(buffer); \ | ||
413 | free(buffer2); | ||
414 | #define _STAGE1(a) fprintf(stderr, "[INFO] Stage 1 at 0x%x\n", a); \ | ||
415 | SEND_COMMAND(VR_PROGRAM_START1, a); | ||
416 | #define _STAGE2(a) fprintf(stderr, "[INFO] Stage 2 at 0x%x\n", a); \ | ||
417 | SEND_COMMAND(VR_PROGRAM_START2, a); | ||
418 | #define _FLUSH fprintf(stderr, "[INFO] Flushing caches...\n"); \ | ||
419 | SEND_COMMAND(VR_FLUSH_CACHES, 0); | ||
420 | #ifdef _WIN32 | ||
421 | #define _SLEEP(x) Sleep(x*1000); | ||
422 | #else | ||
423 | #define _SLEEP(x) sleep(x); | ||
424 | #endif | ||
425 | int mimic_of(usb_dev_handle *dh) | ||
426 | { | ||
427 | int err, fsize; | ||
428 | unsigned char *buffer, *buffer2; | ||
429 | char cpu[8]; | ||
430 | |||
431 | fprintf(stderr, "[INFO] Start!\n"); | ||
432 | _GET_CPU; | ||
433 | _SET_ADDR(0x8000 << 16); | ||
434 | _SEND_FILE("1.bin"); | ||
435 | _GET_CPU; | ||
436 | _VERIFY_DATA("1.bin", 0x8000 << 16); | ||
437 | _STAGE1(0x8000 << 16); | ||
438 | _SLEEP(3); | ||
439 | _VERIFY_DATA("2.bin", 0xB3020060); | ||
440 | _GET_CPU; | ||
441 | _GET_CPU; | ||
442 | _FLUSH; | ||
443 | _GET_CPU; | ||
444 | _GET_CPU; | ||
445 | _SET_ADDR(0x8000 << 16); | ||
446 | _SEND_FILE("3.bin"); | ||
447 | _GET_CPU; | ||
448 | _VERIFY_DATA("3.bin", 0x8000 << 16); | ||
449 | _GET_CPU; | ||
450 | _FLUSH; | ||
451 | _GET_CPU; | ||
452 | _GET_CPU; | ||
453 | _SET_ADDR(0x80D0 << 16); | ||
454 | _SEND_FILE("4.bin"); | ||
455 | _GET_CPU; | ||
456 | _VERIFY_DATA("4.bin", 0x80D0 << 16); | ||
457 | _GET_CPU; | ||
458 | _FLUSH; | ||
459 | _GET_CPU; | ||
460 | _GET_CPU; | ||
461 | _SET_ADDR(0x80E0 << 16); | ||
462 | _SEND_FILE("5.bin"); | ||
463 | _GET_CPU; | ||
464 | _VERIFY_DATA("5.bin", 0x80E0 << 16); | ||
465 | _GET_CPU; | ||
466 | _FLUSH; | ||
467 | _GET_CPU; | ||
468 | _GET_CPU; | ||
469 | _SET_ADDR(0x80004000); | ||
470 | _SEND_FILE("6.bin"); | ||
471 | _GET_CPU; | ||
472 | _VERIFY_DATA("6.bin", 0x80004000); | ||
473 | _GET_CPU; | ||
474 | _FLUSH; | ||
475 | _GET_CPU; | ||
476 | _GET_CPU; | ||
477 | _SET_ADDR(0x80FD << 16); | ||
478 | _SEND_FILE("7.bin"); | ||
479 | _GET_CPU; | ||
480 | _VERIFY_DATA("7.bin", 0x80FD << 16); | ||
481 | _GET_CPU; | ||
482 | _FLUSH; | ||
483 | _GET_CPU; | ||
484 | _STAGE2(0x80FD0004); | ||
485 | _VERIFY_DATA("8.bin", 0x80004004); | ||
486 | _VERIFY_DATA("9.bin", 0x80004008); | ||
487 | _SLEEP(2); | ||
488 | _GET_CPU; | ||
489 | _SET_ADDR(0x80E0 << 16); | ||
490 | _SEND_FILE("10.bin"); | ||
491 | _GET_CPU; | ||
492 | _VERIFY_DATA("10.bin", 0x80E0 << 16); | ||
493 | _GET_CPU; | ||
494 | _FLUSH; | ||
495 | _GET_CPU; | ||
496 | _STAGE2(0x80e00008); | ||
497 | fprintf(stderr, "[INFO] Done!\n"); | ||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | void jzconnect(int address, unsigned char* buf, int len, int func) | ||
502 | { | ||
503 | struct usb_bus *bus; | ||
504 | struct usb_device *tmp_dev; | ||
505 | struct usb_device *dev = NULL; | ||
506 | usb_dev_handle *dh; | ||
507 | int err; | ||
508 | |||
509 | fprintf(stderr,"[INFO] Searching for device...\n"); | ||
510 | |||
511 | usb_init(); | ||
512 | if(usb_find_busses() < 0) | ||
513 | { | ||
514 | fprintf(stderr, "[ERR] Could not find any USB busses.\n"); | ||
515 | return; | ||
516 | } | ||
517 | |||
518 | if (usb_find_devices() < 0) | ||
519 | { | ||
520 | fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n"); | ||
521 | return; | ||
522 | } | ||
523 | |||
524 | for (bus = usb_get_busses(); bus; bus = bus->next) | ||
525 | { | ||
526 | for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next) | ||
527 | { | ||
528 | //printf("Found Vendor %04x Product %04x\n",tmp_dev->descriptor.idVendor, tmp_dev->descriptor.idProduct); | ||
529 | if (tmp_dev->descriptor.idVendor == VID && | ||
530 | tmp_dev->descriptor.idProduct == PID) | ||
531 | { | ||
532 | dev = tmp_dev; | ||
533 | goto found; | ||
534 | |||
535 | } | ||
536 | } | ||
537 | } | ||
538 | |||
539 | if (dev == NULL) | ||
540 | { | ||
541 | fprintf(stderr, "[ERR] Device not found.\n"); | ||
542 | fprintf(stderr, "[ERR] Ensure your device is in USB boot mode and run usbtool again.\n"); | ||
543 | return; | ||
544 | } | ||
545 | |||
546 | found: | ||
547 | if ( (dh = usb_open(dev)) == NULL) | ||
548 | { | ||
549 | fprintf(stderr,"[ERR] Unable to open device.\n"); | ||
550 | return; | ||
551 | } | ||
552 | |||
553 | err = usb_set_configuration(dh, 1); | ||
554 | |||
555 | if (err < 0) | ||
556 | { | ||
557 | fprintf(stderr, "[ERR] usb_set_configuration failed (%d, %s)\n", err, usb_strerror()); | ||
558 | usb_close(dh); | ||
559 | return; | ||
560 | } | ||
561 | |||
562 | /* "must be called" written in the libusb documentation */ | ||
563 | err = usb_claim_interface(dh, 0); | ||
564 | if (err < 0) | ||
565 | { | ||
566 | fprintf(stderr, "[ERR] Unable to claim interface (%d, %s)\n", err, usb_strerror()); | ||
567 | usb_close(dh); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | fprintf(stderr,"[INFO] Found device, uploading application.\n"); | ||
572 | |||
573 | /* Now we can transfer the application to the device. */ | ||
574 | |||
575 | switch(func) | ||
576 | { | ||
577 | case 1: | ||
578 | case 5: | ||
579 | err = upload_app(dh, address, buf, len, (func == 5)); | ||
580 | break; | ||
581 | case 2: | ||
582 | err = read_data(dh, address, buf, len); | ||
583 | break; | ||
584 | case 3: | ||
585 | err = test_device(dh); | ||
586 | break; | ||
587 | case 4: | ||
588 | err = probe_device(dh); | ||
589 | break; | ||
590 | case 6: | ||
591 | err = mimic_of(dh); | ||
592 | break; | ||
593 | } | ||
594 | |||
595 | /* release claimed interface */ | ||
596 | usb_release_interface(dh, 0); | ||
597 | |||
598 | usb_close(dh); | ||
599 | } | ||
600 | |||
601 | void print_usage(void) | ||
602 | { | ||
603 | #ifdef _WIN32 | ||
604 | fprintf(stderr, "Usage: usbtool.exe [CMD] [FILE] [ADDRESS] [LEN]\n"); | ||
605 | #else | ||
606 | fprintf(stderr, "Usage: usbtool [CMD] [FILE] [ADDRESS] [LEN]\n"); | ||
607 | #endif | ||
608 | fprintf(stderr, "\t[ADDRESS] has to be in 0xHEXADECIMAL format\n"); | ||
609 | fprintf(stderr, "\t[CMD]:\n\t\t1 -> upload file to specified address and boot from it\n\t\t2 -> read data from [ADDRESS] with length [LEN] to [FILE]\n"); | ||
610 | fprintf(stderr, "\t\t3 -> read device status\n\t\t4 -> probe keys (only Onda VX747)\n"); | ||
611 | fprintf(stderr, "\t\t5 -> same as 1 but do a stage 2 boot\n\t\t6 -> mimic OF fw recovery\n"); | ||
612 | #ifdef _WIN32 | ||
613 | fprintf(stderr, "\nExample:\n\t usbtool.exe 1 fw.bin 0x80000000"); | ||
614 | fprintf(stderr, "\n\t usbtool.exe 2 save.bin 0x81000000 1024"); | ||
615 | #else | ||
616 | fprintf(stderr, "\nExample:\n\t usbtool 1 fw.bin 0x80000000"); | ||
617 | fprintf(stderr, "\n\t usbtool 2 save.bin 0x81000000 1024"); | ||
618 | #endif | ||
619 | } | ||
620 | |||
621 | int main(int argc, char* argv[]) | ||
622 | { | ||
623 | unsigned char* buf; | ||
624 | int n, len, address, cmd=0; | ||
625 | FILE* fd; | ||
626 | |||
627 | fprintf(stderr, "USBtool v" VERSION " - (C) 2008 Maurus Cuelenaere\n"); | ||
628 | fprintf(stderr, "This is free software; see the source for copying conditions. There is NO\n"); | ||
629 | fprintf(stderr, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); | ||
630 | |||
631 | if(argc > 1) | ||
632 | sscanf(argv[1], "%d", &cmd); | ||
633 | switch(cmd) | ||
634 | { | ||
635 | case 5: | ||
636 | case 1: | ||
637 | if (strcmp(argv[3], "-1") == 0) | ||
638 | address = 0x80000000; | ||
639 | else | ||
640 | { | ||
641 | if (sscanf(argv[3], "0x%x", &address) <= 0) | ||
642 | { | ||
643 | print_usage(); | ||
644 | return -1; | ||
645 | } | ||
646 | } | ||
647 | |||
648 | fd = fopen(argv[2], "rb"); | ||
649 | if (fd < 0) | ||
650 | { | ||
651 | fprintf(stderr, "[ERR] Could not open %s\n", argv[2]); | ||
652 | return 4; | ||
653 | } | ||
654 | |||
655 | len = filesize(fd); | ||
656 | |||
657 | if (len > MAX_FIRMWARESIZE) | ||
658 | { | ||
659 | fprintf(stderr, "[ERR] Firmware file too big\n"); | ||
660 | fclose(fd); | ||
661 | return 5; | ||
662 | } | ||
663 | |||
664 | buf = malloc(len); | ||
665 | if (buf == NULL) | ||
666 | { | ||
667 | fprintf(stderr, "[ERR] Could not allocate memory.\n"); | ||
668 | fclose(fd); | ||
669 | return 6; | ||
670 | } | ||
671 | |||
672 | n = fread(buf, 1, len, fd); | ||
673 | if (n != len) | ||
674 | { | ||
675 | fprintf(stderr, "[ERR] Short read.\n"); | ||
676 | fclose(fd); | ||
677 | return 7; | ||
678 | } | ||
679 | fclose(fd); | ||
680 | |||
681 | fprintf(stderr, "[INFO] File size: %d bytes\n", n); | ||
682 | |||
683 | jzconnect(address, buf, len, cmd); | ||
684 | break; | ||
685 | case 2: | ||
686 | if (sscanf(argv[3], "0x%x", &address) <= 0) | ||
687 | { | ||
688 | print_usage(); | ||
689 | return -1; | ||
690 | } | ||
691 | |||
692 | fd = fopen(argv[2], "wb"); | ||
693 | if (fd < 0) | ||
694 | { | ||
695 | fprintf(stderr, "[ERR] Could not open %s\n", argv[2]); | ||
696 | return 4; | ||
697 | } | ||
698 | |||
699 | sscanf(argv[4], "%d", &len); | ||
700 | |||
701 | buf = malloc(len); | ||
702 | if (buf == NULL) | ||
703 | { | ||
704 | fprintf(stderr, "[ERR] Could not allocate memory.\n"); | ||
705 | fclose(fd); | ||
706 | return 6; | ||
707 | } | ||
708 | |||
709 | jzconnect(address, buf, len, 2); | ||
710 | |||
711 | n = fwrite(buf, 1, len, fd); | ||
712 | if (n != len) | ||
713 | { | ||
714 | fprintf(stderr, "[ERR] Short write.\n"); | ||
715 | fclose(fd); | ||
716 | return 7; | ||
717 | } | ||
718 | fclose(fd); | ||
719 | break; | ||
720 | case 3: | ||
721 | case 4: | ||
722 | case 6: | ||
723 | jzconnect(address, NULL, 0, cmd); | ||
724 | break; | ||
725 | default: | ||
726 | print_usage(); | ||
727 | return 1; | ||
728 | break; | ||
729 | } | ||
730 | |||
731 | return 0; | ||
732 | } | ||