]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blob - host/app/usb_sendhex/usb_sendhex.c
usb_sendhex: extend support for I32HEX format variant.
[fpga/lx-cpu1/lx-rocon.git] / host / app / usb_sendhex / usb_sendhex.c
1 /* usb_sendhex - program for manage device firmware by USB
2  * R.Bartosinski <bartosr@centrum.cz> (C)2004
3  *
4  * Based on 'ul_sendhex'
5  *
6  * Version 1.1 - 2013/08/26
7  */
8 #define _GNU_SOURCE
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <getopt.h>
14 #include <usb.h>
15 #include <sys/time.h>
16 #include <stdint.h>
17 #include <endian.h>
18
19 #if !defined(_WIN32) && !defined(__DJGPP__) && !defined(HAS_GETDELIM)
20 #define HAS_GETDELIM
21 #endif
22 #define HAS_GETOPT_LONG
23
24 #define USB_DEV_VID 0xDEAD
25 #define USB_DEV_PID 0x1000
26
27 #define USB_TIMEOUT 500
28
29 // USB vendor defines
30
31 #define USB_VENDOR_GET_CAPABILITIES  0x00 // get capabilities
32 #define USB_VENDOR_RESET_DEVICE      0x08
33 // #define USB_VENDOR_SET_BYTE          0x10
34 // #define USB_VENDOR_SET_WORD          0x20
35 #define USB_VENDOR_GET_SET_MEMORY    0x30
36 #define USB_VENDOR_ERASE_MEMORY      0x40 // erase memory for 1 Byte
37 #define USB_VENDOR_ERASE_1KB_MEMORY  0x48 // erase memory for 1 KB
38 #define USB_VENDOR_MASS_ERASE        0x50 // erase all device memory
39 #define USB_VENDOR_GOTO              0x60
40 #define USB_VENDOR_CALL              0x70
41 #define USB_VENDOR_GET_STATUS        0xF0
42 #define USB_VENDOR_MASK              0xF8 // mask for vendor commands
43
44 #define USB_VENDOR_MEMORY_BY_BULK    0x80
45
46 int vid = USB_DEV_VID;
47 int pid = USB_DEV_PID;
48 int upload_flg = 0;
49 int mem_type   = 2;
50 unsigned long mem_start  = 0;
51 unsigned long mem_length = 0xff00;
52 unsigned long max_block  = 1024;
53 unsigned long go_addr    = 3;
54 int go_flg     = 0;
55 int call       = 0xFFFF;
56 int arg        = 0;
57 int call_flg   = 0;
58 int reset_flg  = 0;
59 int prt_modules = 0;
60 int debugk     = 0;
61 int debugk_flg = 0;
62 int verbose    = 0;
63 int wait_for_device_flg = 0;
64 char *file_format = NULL;
65 int regerase_flg = 0;
66 int masserase_flg = 0;
67 unsigned long masserase_mode = 0;
68
69 /*****************************************************************************/
70
71 typedef struct tform_file
72 {
73   unsigned char *buf;
74   int   buf_len;
75   int   buf_addr;
76   int   buf_bytes;
77   FILE *file;
78   unsigned char *line_buf;
79   int  line_addr;
80   int  ext_base_addr;
81   int  line_bytes;
82   int  line_offs;
83   int  start_addr;
84   int (*read)(struct tform_file *tform);
85   int (*done)(struct tform_file *tform);
86 } tform_file;
87
88 /*****************************************************************************/
89
90 #if __BYTE_ORDER == __BIG_ENDIAN
91 uint16_t usb_swab16(uint16_t x)
92 {
93   return x << 8 | x >> 8;
94 }
95 #else
96 uint16_t usb_swab16(uint16_t x)
97 {
98   return x;
99 }
100 #endif
101
102 #ifndef HAS_GETDELIM
103 int getdelim(char **line, size_t *linelen, char delim, FILE *F)
104 {
105   char c;
106   size_t l = 0;
107
108   do
109   {
110     if (l + 1 >= *linelen)
111     {
112       *linelen = l + 20;
113
114       if (!*line)
115         *line = (char *)malloc(*linelen);
116       else
117         *line = (char *)realloc(*line, *linelen);
118     }
119
120     c = fgetc(F);
121
122     if (feof(F))
123     {
124       if (l)
125         break;
126       else
127         return -1;
128     }
129
130     if (c != '\r')
131       (*line)[l++] = c;
132   }
133   while (c != delim);
134
135   (*line)[l] = 0;
136   return l;
137 }
138 #endif
139
140 int get_hex(char **p, unsigned *v, int chars)
141 {
142   unsigned u = 0;
143   char c;
144   *v = 0;
145
146   while (**p == ' ')
147     (*p)++;
148
149   while (chars--)
150   {
151     u <<= 4;
152     c = **p;
153
154     if ((c >= '0') && (c <= '9'))
155       u += c - '0';
156     else if ((c >= 'A') && (c <= 'F'))
157       u += c - 'A' + 10;
158     else
159       return -1;
160
161     (*p)++;
162   };
163
164   *v = u;
165
166   return 0;
167 }
168
169 int tform_init(tform_file *tform, int buf_len)
170 {
171   if (!buf_len) buf_len = 1024;
172
173   tform->file = NULL;
174   tform->buf_len = buf_len;
175   tform->buf = malloc(tform->buf_len);
176   tform->buf_addr = 0;
177   tform->line_buf = NULL;
178   tform->line_offs = 0;
179   tform->line_bytes = 0;
180   tform->start_addr = -1;
181   tform->buf_bytes = 0;
182   tform->read = NULL;
183   tform->done = NULL;
184   tform->ext_base_addr = 0;
185   return 0;
186 }
187
188 int tform_done(tform_file *tform)
189 {
190   if (tform->done)
191     return tform->done(tform);
192
193   fclose(tform->file);
194
195   if (tform->buf)
196     free(tform->buf);
197
198   if (tform->line_buf)
199     free(tform->line_buf);
200
201   return 0;
202 };
203
204 int tform_read(tform_file *tform)
205 {
206   return tform->read(tform);
207 }
208
209 int tform_read_ihex(tform_file *tform)
210 {
211   int cn, len = 0;
212   int addr = 0;
213   unsigned u, v;
214   char *p;
215   unsigned char *r;
216   char *line = NULL;
217   size_t line_len = 0;
218
219   while (len < tform->buf_len)
220   {
221     if (!tform->line_bytes)
222     {
223       int checksum = 0;
224       int ihex_type = 0;
225
226       tform->line_offs = 0;
227
228       if (getdelim(&line, &line_len, '\n', tform->file) == -1)
229         break;
230
231       p = line;
232
233       if (*p++ != ':')
234         printf("tform_read : strange line %s\n", line);
235       else
236       {
237         if (get_hex(&p, &u, 2) < 0)
238         {
239           printf("tform_read_ihex : bad ihex cnt\n");
240           return -1;
241         }
242
243         checksum += cn = tform->line_bytes = u;
244
245         if (!tform->line_buf)
246           tform->line_buf = malloc(cn);
247         else
248           tform->line_buf = realloc(tform->line_buf, cn);
249
250         if (get_hex(&p, &u, 2) < 0)
251         {
252           printf("tform_read_ihex : bad ihex addr\n");
253           return -1;
254         }
255
256         if (get_hex(&p, &v, 2) < 0)
257         {
258           printf("tform_read_ihex : bad ihex addr\n");
259           return -1;
260         }
261
262         checksum += u + v;
263         tform->line_addr = (u << 8) + v;
264
265         if (get_hex(&p, &u, 2) < 0)
266         {
267           printf("tform_read_ihex : bad ihex type\n");
268           return -1;
269         }
270
271         checksum += ihex_type = u;
272
273         if ((ihex_type >= 0) && (ihex_type <= 5))
274         {
275           r = tform->line_buf;
276
277           while (cn--)
278           {
279             if (get_hex(&p, &u, 2) < 0)
280             {
281               printf("tform_read_ihex : bad ihex data\n");
282               return -1;
283             }
284
285             checksum += *r++ = u;
286           }
287
288           if (get_hex(&p, &u, 2) < 0)
289           {
290             printf("tform_read_ihex : bad ihex csum\n");
291             return -1;
292           }
293
294           checksum += u;
295
296           if (checksum & 0xff)
297           {
298             printf("tform_read_ihex : error ihex csum %d\n",
299                    checksum);
300             return -1;
301           }
302
303           while ((u = *p++)) if (u != ' ' && u != '\n' && u != '\r')
304           {
305             printf("tform_read_ihex : residual chars on line\n");
306             return -1;
307           }
308         }
309
310         if (ihex_type == 1)
311         {
312           tform->line_bytes = 0;
313           if(tform->start_addr == -1)
314             tform->start_addr = tform->line_addr;
315         }
316
317         tform->line_addr+=tform->ext_base_addr;
318
319         if((ihex_type >= 2) && (ihex_type <= 5))
320         {
321           cn = tform->line_bytes;
322           r = tform->line_buf;
323           addr = 0;
324
325           while(cn-- > 0)
326           {
327             addr <<= 8;
328             addr += *(r++);
329           }
330           if(ihex_type == 2)
331             tform->ext_base_addr=addr << 4;
332           else if(ihex_type == 4)
333             tform->ext_base_addr = addr << 16;
334           else if(ihex_type == 5)
335             tform->start_addr = addr;
336
337           tform->line_bytes = 0;
338         }
339       }
340     }
341
342     if (tform->line_bytes)
343     {
344       if (!len)
345         addr = tform->buf_addr = tform->line_addr + tform->line_offs;
346       else if (addr != tform->line_addr + tform->line_offs)
347         break;
348
349       cn = tform->line_bytes - tform->line_offs;
350
351       if (cn + len > tform->buf_len) cn = tform->buf_len - len;
352
353       memcpy(tform->buf + len, tform->line_buf + tform->line_offs, cn);
354       len += cn;
355       addr += cn;
356       tform->line_offs += cn;
357
358       if (tform->line_bytes == tform->line_offs)
359         tform->line_bytes = 0;
360     }
361   }
362
363   tform->buf_bytes = len;
364
365   return len;
366 }
367
368 int tform_read_binary(tform_file *tform)
369 {
370   int len = 0;
371
372   tform->buf_addr += tform->buf_bytes;
373   len = fread(tform->buf, 1, tform->buf_len, tform->file);
374
375   if (len < 0)
376   {
377     perror("tform_read_binary : read error");
378     return -1;
379   }
380
381   tform->buf_bytes = len;
382   return len;
383 }
384
385 int tform_open(tform_file *tform, char *file_name,
386                char *format, int buf_len, int wr_fl)
387 {
388   FILE *file;
389
390   if (!format || !strcmp("ihex", format))
391   {
392     if ((file = fopen(file_name, "r")) == NULL)
393     {
394       perror("download_file : hex file open");
395       return -1;
396     }
397
398     tform_init(tform, buf_len);
399     tform->file = file;
400     tform->read = tform_read_ihex;
401   }
402   else if (!strcmp("binary", format))
403   {
404     if ((file = fopen(file_name, "rb")) == NULL)
405     {
406       perror("download_file : binary file open");
407       return -1;
408     };
409
410     tform_init(tform, buf_len);
411     tform->file = file;
412     tform->read = tform_read_binary;
413   }
414   else
415   {
416     fprintf(stderr, "requested unknown format %s\n", format);
417     return -1;
418   }
419
420   return 1;
421 }
422
423
424 /*****************************************************************************/
425 /*****************************************************************************/
426 /*****************************************************************************/
427 /* USB functions */
428 void print_devices(void)
429 {
430   struct usb_bus *bus;
431   struct usb_device *dev;
432   int i = 0;
433
434   usb_init(); // NO for more devices
435   usb_find_busses();
436   usb_find_devices();
437
438   printf("All connected usb devices\n");
439   printf("  bus/device    idVendor/idProduct\n");
440
441   for (bus = usb_busses; bus; bus = bus->next)
442   {
443     for (dev = bus->devices; dev; dev = dev->next)
444     {
445       i++;
446       printf("    %s/%s     0x%04X/0x%04X\n", bus->dirname, dev->filename, dev->descriptor.idVendor, dev->descriptor.idProduct);
447     }
448   }
449
450   if (!i)
451     printf(" -- no device.\n");
452 }
453
454 struct usb_device *find_usb_device(int vendor, int product)
455 {
456   struct usb_bus *bus;
457   struct usb_device *dev;
458
459   for (bus = usb_busses; bus; bus = bus->next)
460   {
461     for (dev = bus->devices; dev; dev = dev->next)
462     {
463       if ((dev->descriptor.idVendor == vendor) &&
464           (dev->descriptor.idProduct) == product)
465         return dev;
466     }
467   }
468
469   return NULL;
470 }
471
472 usb_dev_handle *usb_open_device(int uvid, int upid)
473 {
474   struct usb_device *dev;
475   usb_dev_handle *hdev;
476
477   usb_init(); // NO for more devices
478   usb_find_busses();
479   usb_find_devices();
480
481   dev = find_usb_device(uvid, upid);
482
483   if (!dev)
484   {
485     if (verbose)
486       printf("!!! Cannot find device 0x%04X:0x%04X\n", uvid, upid);
487
488     return NULL;
489   }
490
491   if ((hdev = usb_open(dev)) == NULL)
492   {
493     if (verbose)
494       printf("!!! USB device wasn't opened !!!\n");
495
496     return NULL;
497   }
498
499   usb_claim_interface(hdev, 0);
500
501   if (verbose)
502     printf(" USB Device 0x%04X:0x%04X '%s' is open.\n", uvid, upid, dev->filename);
503
504   return hdev;
505 }
506
507 int usb_close_device(usb_dev_handle *hdev)
508 {
509   int bRes = 1;
510   usb_release_interface(hdev, 0);
511   bRes = usb_close(hdev);
512
513   if (bRes && verbose)
514     printf("!!! USB Device wasn't closed !!!\n");
515
516   return bRes;
517 }
518
519 /*****************************************************************************/
520 /*****************************************************************************/
521 /*****************************************************************************/
522
523 int download_file(char *file_name, char *format)
524 {
525   usb_dev_handle *hdev;
526   tform_file tform;
527   int len;
528   int i;
529   int ret = 0;
530 //  int stamp;
531   unsigned long shift_addr = 0;
532
533   struct timeval time1, time2;
534   struct timezone tz;
535
536   shift_addr = mem_start;
537
538   hdev = usb_open_device(vid, pid);
539
540   if (!hdev)
541   {
542     perror("download_file : usb device open failed");
543     return -1;
544   }
545
546   /* ul_drv_debflg(ul_fd,0x11); */ /* 0x9 0x11 */
547
548   if (tform_open(&tform, file_name, format, max_block, 0) < 0)
549   {
550     usb_close_device(hdev);
551     return -1;
552   }
553
554   gettimeofday(&time1, &tz);
555
556   do
557   {
558     len = tform_read(&tform);
559
560     if (!len) break;
561
562     if (len < 0)
563     {
564       perror("download_file : ihex");
565       ret = -1;
566       break;
567     }
568
569     printf("addr %4lX len %4X\n", tform.buf_addr + shift_addr, len);
570
571     /* send data */
572
573     //  if((stamp=ul_new_memrq_write(ul_fd,module,mem_type,
574     //     tform.buf_addr+shift_addr,len,tform.buf))<0)
575     //  { printf("download_file : send message error\n");
576     //    ret=-1; break;
577     //  };
578     i = 3;
579
580     do
581     {
582       ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, USB_VENDOR_GET_SET_MEMORY | mem_type /*USB_VENDOR_TARGET_XDATA*/,
583                             (unsigned long)(tform.buf_addr + shift_addr) & 0xffff, (((unsigned long)(tform.buf_addr + shift_addr)) >> 16) & 0xffff, (void *)tform.buf, len, 150 + len); //USB_TIMEOUT);
584 //      ret = usb_bulk_write( hdev, USB_ENDPOINT_IN | 0x02, buf, len, 1000);
585
586       if (verbose && ret < 0)  printf("Mem read error %d - again\n", ret);
587
588       i--;
589     }
590     while (ret < 0 && i);
591
592   }
593   while (1);
594
595   gettimeofday(&time2, &tz);
596
597   if (verbose)
598   {
599     long dus = (time2.tv_sec * 1000000 + time2.tv_usec) - (time1.tv_sec * 1000000 + time1.tv_usec);
600     printf("Upload time %lu.%lu s\n", dus / 1000000, dus % 1000000);
601   }
602
603
604   if (tform.start_addr != -1)
605     printf("Found start address %4X\n", tform.start_addr);
606
607   tform_done(&tform);
608   usb_close_device(hdev);
609   return ret;
610 }
611
612 int send_cmd_call(int cmd, int val)
613 {
614   int ret, resp_val;
615   usb_dev_handle *hdev;
616   char resp[10];
617
618   hdev = usb_open_device(vid, pid);
619
620   if (!hdev)
621   {
622     perror("send_cmd_call : USB open failed");
623     return -1;
624   }
625
626   ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
627                         USB_VENDOR_CALL, val & 0xffff, cmd & 0xffff, resp, sizeof(resp), USB_TIMEOUT);
628   resp_val = usb_swab16(*((uint16_t *)(resp)));
629
630   if (ret < 0)
631     printf("Call %4X (%4X) ERROR %d: %s\n", (uint16_t)(cmd & 0xffff), (uint16_t)(val & 0xffff), ret, usb_strerror());
632   else
633     printf("Call %4X (%4X): %4X\n", (uint16_t)(cmd & 0xffff), (uint16_t)(val & 0xffff), resp_val);
634
635   usb_close_device(hdev);
636   return ret;
637 }
638
639 int send_cmd_go(unsigned long addr)
640 {
641   int ret;
642   usb_dev_handle *hdev;
643
644   hdev = usb_open_device(vid, pid);
645
646   if (!hdev)
647   {
648     perror("send_cmd_go : USB open failed");
649     return -1;
650   }
651
652   ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
653                         USB_VENDOR_GOTO, addr & 0xffff, (addr >> 16) & 0xffff, NULL, 0, USB_TIMEOUT);
654
655   if (ret < 0) printf("Goto to %4lX ERROR %d: %s\n", addr, ret, usb_strerror());
656   else printf("Goto to %4lX OK\n", addr);
657
658   usb_close_device(hdev);
659   return ret;
660 }
661
662 int send_cmd_reset()
663 {
664   int ret;
665   usb_dev_handle *hdev;
666
667   hdev = usb_open_device(vid, pid);
668
669   if (!hdev)
670   {
671     perror("send_cmd_reset : USB open failed");
672     return -1;
673   }
674
675   ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
676                         USB_VENDOR_RESET_DEVICE, 0, 0, NULL, 0, USB_TIMEOUT);
677
678   if (ret < 0)
679     printf("Reset device ERROR %d: %s\n", ret, usb_strerror());
680   else
681     printf("Reset OK\n");
682
683   usb_close_device(hdev);
684   return ret;
685 };
686
687
688 int send_cmd_regerase(unsigned long addr, unsigned long len)
689 {
690   int ret;
691   usb_dev_handle *hdev;
692
693   hdev = usb_open_device(vid, pid);
694
695   if (!hdev)
696   {
697     perror("send_cmd_regerase : USB open failed");
698     return -1;
699   }
700
701   if (addr + len < 0x10000)
702   {
703     ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
704                           USB_VENDOR_ERASE_MEMORY, addr, len, NULL, 0, USB_TIMEOUT * 5);
705   }
706   else
707   {
708     len += addr & 0x3ff;
709     ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
710                           USB_VENDOR_ERASE_1KB_MEMORY, addr >> 10, len >> 10, NULL, 0, USB_TIMEOUT * 10);
711   }
712
713   if (ret < 0)
714     printf("Region Erase from %4lX ERROR %d: %s\n", addr, ret, usb_strerror());
715   else
716     printf("Region Erase from %4lX OK\n", addr);
717
718   usb_close_device(hdev);
719   return ret;
720 };
721
722
723
724 int send_cmd_masserase(unsigned long mode)
725 {
726   int ret;
727   usb_dev_handle *hdev;
728
729   hdev = usb_open_device(vid, pid);
730
731   if (!hdev)
732   {
733     perror("send_cmd_masserase : USB open failed");
734     return -1;
735   };
736
737   ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
738                         USB_VENDOR_MASS_ERASE, mode & 0xffff, (mode >> 16) & 0xffff, NULL, 0, USB_TIMEOUT * 20);
739
740   if (ret < 0)
741     printf("Mass Erase to %4lX ERROR %d: %s\n", mode, ret, usb_strerror());
742   else printf("Mass Erase to %4lX OK\n", mode);
743
744   usb_close_device(hdev);
745   return ret;
746 };
747
748
749 int upload_file(char *file_name, char *format)
750 {
751   usb_dev_handle *hdev;
752   FILE *file;
753   int ret = 0;
754   unsigned char buf[0x400];
755   unsigned char *p;
756   char *mode = "w";
757   enum {fmt_ihex, fmt_binary, fmt_dump} fmt;
758   int i, l, csum;
759   unsigned long mem_adr = mem_start;
760   unsigned long mem_len = mem_length;
761   unsigned long len;
762   unsigned long ext_addr = 0; /* for Intel HEX format */
763
764   struct timeval time1, time2;
765   struct timezone tz;
766
767   if (max_block > 0x400)
768     max_block = 0x400;
769
770   if (!format || !strcmp("ihex", format))
771     fmt = fmt_ihex;
772   else if (!strcmp("binary", format))
773   {
774     mode = "wb";
775     fmt = fmt_binary;
776   }
777   else if (!strcmp("dump", format))
778     fmt = fmt_dump;
779   else
780   {
781     fprintf(stderr, "requested unknown format %s\n", format);
782     return -1;
783   }
784
785   if (!strcmp(file_name, "-"))
786     file_name = NULL;
787
788   hdev = usb_open_device(vid, pid);
789
790   if (!hdev)
791   {
792     perror("upload_file : open failed");
793     return -1;
794   };
795
796   /* ul_drv_debflg(ul_fd,0x11); */ /* 0x9 0x11 */
797
798   if (file_name)
799   {
800     if ((file = fopen(file_name, mode)) == NULL)
801     {
802       perror("upload_file : file open");
803       usb_close_device(hdev);
804       return -1;
805     }
806   }
807   else file = stdout;
808
809   gettimeofday(&time1, &tz);
810
811 //  ret = usb_control_msg( hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, USB_VENDOR_MEMORY_BY_BULK | USB_VENDOR_TARGET_XDATA,
812 //                            mem_adr & 0xffff, mem_len, NULL, 0, 2000); //USB_TIMEOUT);
813
814   if (ret < 0)
815   {
816     printf("ERR ctrl msg\n");
817     mem_len = 0;
818   }
819
820   while (mem_len)
821   {
822     len = mem_len < max_block ? mem_len : max_block;
823     /* read data */
824     i = 3;
825
826     do
827     {
828       ret = usb_control_msg(hdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, USB_VENDOR_GET_SET_MEMORY | mem_type /*USB_VENDOR_TARGET_XDATA*/,
829                             mem_adr & 0xffff, (mem_adr >> 16) & 0xffff, (void *)buf, len, 100 + len); //USB_TIMEOUT);
830 //      ret = usb_bulk_read( hdev, USB_ENDPOINT_IN | 0x02, buf, len, 1000);
831
832       if (verbose && ret < 0)
833         printf("Mem read error - again\n");
834
835       i--;
836     }
837     while (ret < 0 && i);
838
839     if (ret < 0)
840     {
841       printf("Mem read returns %d: %s\n", ret, usb_strerror());
842       break;
843     }
844
845     if (file_name) printf("%04lX\n", mem_adr);
846
847     switch (fmt)
848     {
849       case fmt_ihex:
850         p = buf;
851         i = 0;
852
853         while (i < len)
854         {
855           unsigned long a = mem_adr + i;
856
857           if ((a & ~0xFFFF) != ext_addr)
858           {
859             unsigned long val;
860             unsigned char b;
861
862             ext_addr = a & ~0xFFFF;
863             val = ext_addr >> 16;
864             l = 2;
865             val >>= 16;
866             while (val != 0)
867             {
868               val >>= 8;
869               l++;
870             }
871             fprintf(file, ":%02X000004", l);
872             csum = l + 4;
873             val = ext_addr >> 16;
874             while (l--)
875             {
876               b = (val >> (8 * l)) & 0xff;
877               fprintf(file, "%02X", b);
878               csum += b;
879             }
880             fprintf(file, "%02X\n", (-csum) & 0xFF);
881           }
882
883           l = len - i;
884
885           if (l > 16) l = 16;
886
887           csum = l + a + (a >> 8);
888           fprintf(file, ":%02X%04lX00", l, a & 0xffff);
889
890           while (l--)
891           {
892             fprintf(file, "%02X", buf[i]);
893             csum += buf[i++];
894           };
895
896           fprintf(file, "%02X\n", (-csum) & 0xFF);
897         }
898
899         break;
900
901       case fmt_binary:
902         if (fwrite(buf, len, 1, file) != 1)
903         {
904           perror("upload_file : file write");
905           return -1;
906         }
907
908         break;
909
910       case fmt_dump:
911         i = 0;
912         p = buf;
913
914         while (i < len)
915         {
916           if (i & 0xf) printf(" %02X", *(p++));
917           else printf(i ? "\n%04lX:%02X" : "%04lX:%02X", mem_adr + i, *(p++));
918
919           i++;
920         }
921
922         printf("\n");
923         break;
924     }
925
926     mem_adr += len;
927     mem_len -= len;
928   }
929
930   gettimeofday(&time2, &tz);
931
932   if (verbose)
933   {
934     long dus = (time2.tv_sec * 1000000 + time2.tv_usec) - (time1.tv_sec * 1000000 + time1.tv_usec);
935     printf("Upload time %lu.%lu s\n", dus / 1000000, dus % 1000000);
936   }
937
938   if (fmt == fmt_ihex)
939     fprintf(file, ":00000001FF\n");
940
941   if (file_name)
942     fclose(file);
943
944   usb_close_device(hdev);
945
946   return 0;
947 };
948
949 static int wait_for_device(int timeout)
950 {
951   usb_dev_handle *hdev;
952
953   while (timeout)
954   {
955     hdev = usb_open_device(vid, pid);
956
957     if (hdev)
958       break;
959
960 #ifdef _WIN32
961     Sleep(1000);
962 #else
963     sleep(1);
964 #endif
965     timeout--;
966   }
967
968   return timeout ? 0 : -1;
969 }
970
971 /*****************************************************************************/
972 /*****************************************************************************/
973 /*****************************************************************************/
974
975 static void
976 usage(void)
977 {
978   printf("Usage: usb_sendhex <parameters> <hex_file>\n");
979   printf("  -d, --vid <num>          device vendor id (VID) [0x%04X]\n", USB_DEV_VID);
980   printf("  -i, --pid <num>          product id (PID) [0x%04X]\n", USB_DEV_PID);
981   printf("  -t, --type <num>         target module memory space\n");
982   printf("  -s, --start <addr>       start address of transfer\n");
983   printf("  -l, --length <num>       length of upload block\n");
984   printf("  -b, --block <num>        maximal block length\n");
985   printf("  -c, --call <num>         vendor custom call\n");
986   printf("  -a, --argument <num>     argument for vendor custom call\n");
987   printf("  -g, --go <addr>          start program from address\n");
988   printf("  -r, --reset              reset before download\n");
989   printf("  -E, --mass-erase <mode>  full device erase\n");
990   printf("  -e, --erase              erase region defined by -s -l\n");
991   printf("  -u, --upload             upload memory block [download]\n");
992   printf("  -w, --wait               wait for device to be on\n");
993   printf("  -f, --format <format>    format of data file [ihex]\n");
994   printf("  -p, --print              print devices\n");
995   printf("      --debug-kernel <m>   flags to debug kernel\n");
996   printf("  -v, --verbose            verbose program\n");
997   printf("  -V, --version            show version\n");
998   printf("  -h, --help               this usage screen\n");
999 }
1000
1001 int main(int argc, char *argv[])
1002 {
1003   static struct option long_opts[] =
1004   {
1005     { "vid", 1, 0, 'd' },
1006     { "pid", 1, 0, 'i' },
1007     { "type",  1, 0, 't' },
1008     { "start", 1, 0, 's' },
1009     { "length", 1, 0, 'l' },
1010     { "block", 1, 0, 'b' },
1011     { "call", 1, 0, 'c' },
1012     { "argument", 1, 0, 'a' },
1013     { "go",    1, 0, 'g' },
1014     { "reset", 0, 0, 'r' },
1015     { "mass-erase", 1, 0, 'E' },
1016     { "erase", 0, 0, 'e' },
1017     { "upload", 0, 0, 'u' },
1018     { "wait", 0, 0, 'w' },
1019     { "format", 1, 0, 'f' },
1020     { "print", 0, 0, 'p' },
1021     { "verbose", 0, 0, 'v' },
1022     { "version", 0, 0, 'V' },
1023     { "help",  0, 0, 'h' },
1024     { "debug-kernel", 1, 0, 'D' },
1025     { 0, 0, 0, 0}
1026   };
1027   int opt;
1028
1029 #ifndef HAS_GETOPT_LONG
1030   while ((opt = getopt(argc, argv, "d:i:t:s:l:b:c:a::g:rE:euwf:pvVhD:")) != EOF)
1031 #else
1032   while ((opt = getopt_long(argc, argv, "d:i:t:s:l:b:c:a:g:rE:euwf:pvVh", &long_opts[0], NULL)) != EOF)
1033 #endif
1034
1035     switch (opt)
1036     {
1037       char *p;
1038       case 'd':
1039         vid = strtol(optarg, &p, 16);
1040
1041         if (!p || (p == optarg))
1042         {
1043           printf("usb_sendhex : vendor ID is not hexadecimal number\n");
1044           exit(1);
1045         }
1046
1047         if (*p == ':')
1048         {
1049           char *r = p + 1;
1050           pid = strtol(r, &p, 16);
1051
1052           if (!p || (p == r))
1053           {
1054             printf("usb_sendhex : product ID is not hexadecimal number\n");
1055             exit(1);
1056           }
1057         }
1058
1059         break;
1060       case 'i':
1061         pid = strtol(optarg, &p, 16);
1062         break;
1063       case 't':
1064         mem_type = strtol(optarg, NULL, 0);
1065         break;
1066       case 's':
1067         mem_start = strtoul(optarg, NULL, 0);
1068         break;
1069       case 'l':
1070         mem_length = strtoul(optarg, NULL, 0);
1071         break;
1072       case 'b':
1073         max_block = strtoul(optarg, NULL, 0);
1074         break;
1075       case 'c':
1076         call = strtoul(optarg, NULL, 0);
1077         call_flg = 1;
1078         break;
1079       case 'a':
1080         arg = strtoul(optarg, NULL, 0);
1081         break;
1082       case 'g':
1083         go_addr = strtoul(optarg, NULL, 0);
1084         go_flg = 1;
1085         break;
1086       case 'r':
1087         reset_flg = 1;
1088         break;
1089       case 'E':
1090         masserase_mode = strtoul(optarg, NULL, 0);
1091         masserase_flg = 1;
1092         break;
1093       case 'e':
1094         regerase_flg = 1;
1095         break;
1096       case 'u':
1097         upload_flg = 1;
1098         break;
1099       case 'w':
1100         wait_for_device_flg = 1;
1101         break;
1102       case 'f':
1103         file_format = optarg;
1104         break;
1105       case 'p':
1106         prt_modules = 1;
1107         break;
1108       case 'D':
1109         debugk = strtol(optarg, NULL, 0);
1110         debugk_flg = 1;
1111         break;
1112       case 'v':
1113         verbose = 1;
1114         break;
1115       case 'V':
1116         fputs("USB sendhex v.1.1\n", stdout);
1117         exit(0);
1118       case 'h':
1119       default:
1120         usage();
1121         exit(opt == 'h' ? 0 : 1);
1122     }
1123
1124   if ((optind >= argc) && !go_flg && !call_flg && !prt_modules && !debugk_flg
1125       && !masserase_flg && !regerase_flg && !reset_flg)
1126   {
1127     usage();
1128     exit(1);
1129   }
1130
1131   if (prt_modules)
1132     print_devices();
1133
1134   if (wait_for_device_flg)
1135     if (wait_for_device(100) < 0)
1136       exit(2);
1137
1138   if (reset_flg)
1139     send_cmd_reset();
1140
1141   if (regerase_flg)
1142     send_cmd_regerase(mem_start, mem_length);
1143
1144   if (masserase_flg)
1145     send_cmd_masserase(masserase_mode);
1146
1147   if (!upload_flg)
1148   {
1149     while (optind < argc)
1150       if (download_file(argv[optind++], file_format) < 0)
1151         exit(2);
1152   }
1153   else
1154   {
1155     if (optind + 1 != argc)
1156     {
1157       printf("upload_file : needs exactly one filename\n");
1158       exit(1);
1159     }
1160
1161     if (upload_file(argv[optind], file_format) < 0)
1162       exit(2);
1163   }
1164
1165   if (call_flg)
1166   {
1167     if (send_cmd_call(call, arg) < 0)
1168       exit(2);
1169   }
1170
1171   if (go_flg)
1172   {
1173     if (send_cmd_go(go_addr) < 0)
1174       exit(2);
1175   }
1176
1177   return 0;
1178 }