stream pushing ok without access permission of /dev/video0
[rtmpclient.git] / app / src / main / jni / libusb / examples / ezusb.c
1 /*
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)
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 #include <stdio.h>
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdint.h>
28
29 #include "libusb.h"
30 #include "ezusb.h"
31
32 extern void logerror(const char *format, ...)
33         __attribute__ ((format(printf, 1, 2)));
34
35 /*
36  * This file contains functions for uploading firmware into Cypress
37  * EZ-USB microcontrollers. These chips use control endpoint 0 and vendor
38  * specific commands to support writing into the on-chip SRAM. They also
39  * support writing into the CPUCS register, which is how we reset the
40  * processor after loading firmware (including the reset vector).
41  *
42  * These Cypress devices are 8-bit 8051 based microcontrollers with
43  * special support for USB I/O.  They come in several packages, and
44  * some can be set up with external memory when device costs allow.
45  * Note that the design was originally by AnchorChips, so you may find
46  * references to that vendor (which was later merged into Cypress).
47  * The Cypress FX parts are largely compatible with the Anchorhip ones.
48  */
49
50 int verbose = 1;
51
52 /*
53  * return true if [addr,addr+len] includes external RAM
54  * for Anchorchips EZ-USB or Cypress EZ-USB FX
55  */
56 static bool fx_is_external(uint32_t addr, size_t len)
57 {
58         /* with 8KB RAM, 0x0000-0x1b3f can be written
59          * we can't tell if it's a 4KB device here
60          */
61         if (addr <= 0x1b3f)
62                 return ((addr + len) > 0x1b40);
63
64         /* there may be more RAM; unclear if we can write it.
65          * some bulk buffers may be unused, 0x1b3f-0x1f3f
66          * firmware can set ISODISAB for 2KB at 0x2000-0x27ff
67          */
68         return true;
69 }
70
71 /*
72  * return true if [addr,addr+len] includes external RAM
73  * for Cypress EZ-USB FX2
74  */
75 static bool fx2_is_external(uint32_t addr, size_t len)
76 {
77         /* 1st 8KB for data/code, 0x0000-0x1fff */
78         if (addr <= 0x1fff)
79                 return ((addr + len) > 0x2000);
80
81         /* and 512 for data, 0xe000-0xe1ff */
82         else if (addr >= 0xe000 && addr <= 0xe1ff)
83                 return ((addr + len) > 0xe200);
84
85         /* otherwise, it's certainly external */
86         else
87                 return true;
88 }
89
90 /*
91  * return true if [addr,addr+len] includes external RAM
92  * for Cypress EZ-USB FX2LP
93  */
94 static bool fx2lp_is_external(uint32_t addr, size_t len)
95 {
96         /* 1st 16KB for data/code, 0x0000-0x3fff */
97         if (addr <= 0x3fff)
98                 return ((addr + len) > 0x4000);
99
100         /* and 512 for data, 0xe000-0xe1ff */
101         else if (addr >= 0xe000 && addr <= 0xe1ff)
102                 return ((addr + len) > 0xe200);
103
104         /* otherwise, it's certainly external */
105         else
106                 return true;
107 }
108
109
110 /*****************************************************************************/
111
112 /*
113  * These are the requests (bRequest) that the bootstrap loader is expected
114  * to recognize.  The codes are reserved by Cypress, and these values match
115  * what EZ-USB hardware, or "Vend_Ax" firmware (2nd stage loader) uses.
116  * Cypress' "a3load" is nice because it supports both FX and FX2, although
117  * it doesn't have the EEPROM support (subset of "Vend_Ax").
118  */
119 #define RW_INTERNAL     0xA0    /* hardware implements this one */
120 #define RW_MEMORY       0xA3
121
122 /*
123  * Issues the specified vendor-specific write request.
124  */
125 static int ezusb_write(libusb_device_handle *device, const char *label,
126         uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len)
127 {
128         int status;
129
130         if (verbose > 1)
131                 logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len);
132         status = libusb_control_transfer(device,
133                 LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
134                 opcode, addr & 0xFFFF, addr >> 16,
135                 (unsigned char*)data, (uint16_t)len, 1000);
136         if (status != len) {
137                 if (status < 0)
138                         logerror("%s: %s\n", label, libusb_error_name(status));
139                 else
140                         logerror("%s ==> %d\n", label, status);
141         }
142         return (status < 0) ? -EIO : 0;
143 }
144
145 /*
146  * Issues the specified vendor-specific read request.
147  */
148 static int ezusb_read(libusb_device_handle *device, const char *label,
149         uint8_t opcode, uint32_t addr, const unsigned char *data, size_t len)
150 {
151         int status;
152
153         if (verbose > 1)
154                 logerror("%s, addr 0x%08x len %4u (0x%04x)\n", label, addr, (unsigned)len, (unsigned)len);
155         status = libusb_control_transfer(device,
156                 LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
157                 opcode, addr & 0xFFFF, addr >> 16,
158                 (unsigned char*)data, (uint16_t)len, 1000);
159         if (status != len) {
160                 if (status < 0)
161                         logerror("%s: %s\n", label, libusb_error_name(status));
162                 else
163                         logerror("%s ==> %d\n", label, status);
164         }
165         return (status < 0) ? -EIO : 0;
166 }
167
168 /*
169  * Modifies the CPUCS register to stop or reset the CPU.
170  * Returns false on error.
171  */
172 static bool ezusb_cpucs(libusb_device_handle *device, uint32_t addr, bool doRun)
173 {
174         int status;
175         uint8_t data = doRun ? 0x00 : 0x01;
176
177         if (verbose)
178                 logerror("%s\n", data ? "stop CPU" : "reset CPU");
179         status = libusb_control_transfer(device,
180                 LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
181                 RW_INTERNAL, addr & 0xFFFF, addr >> 16,
182                 &data, 1, 1000);
183         if ((status != 1) &&
184                 /* We may get an I/O error from libusb as the device disappears */
185                 ((!doRun) || (status != LIBUSB_ERROR_IO)))
186         {
187                 const char *mesg = "can't modify CPUCS";
188                 if (status < 0)
189                         logerror("%s: %s\n", mesg, libusb_error_name(status));
190                 else
191                         logerror("%s\n", mesg);
192                 return false;
193         } else
194                 return true;
195 }
196
197 /*
198  * Send an FX3 jumpt to address command
199  * Returns false on error.
200  */
201 static bool ezusb_fx3_jump(libusb_device_handle *device, uint32_t addr)
202 {
203         int status;
204
205         if (verbose)
206                 logerror("transfer execution to Program Entry at 0x%08x\n", addr);
207         status = libusb_control_transfer(device,
208                 LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
209                 RW_INTERNAL, addr & 0xFFFF, addr >> 16,
210                 NULL, 0, 1000);
211         /* We may get an I/O error from libusb as the device disappears */
212         if ((status != 0) && (status != LIBUSB_ERROR_IO))
213         {
214                 const char *mesg = "failed to send jump command";
215                 if (status < 0)
216                         logerror("%s: %s\n", mesg, libusb_error_name(status));
217                 else
218                         logerror("%s\n", mesg);
219                 return false;
220         } else
221                 return true;
222 }
223
224 /*****************************************************************************/
225
226 /*
227  * Parse an Intel HEX image file and invoke the poke() function on the
228  * various segments to implement policies such as writing to RAM (with
229  * a one or two stage loader setup, depending on the firmware) or to
230  * EEPROM (two stages required).
231  *
232  * image       - the hex image file
233  * context     - for use by poke()
234  * is_external - if non-null, used to check which segments go into
235  *               external memory (writable only by software loader)
236  * poke        - called with each memory segment; errors indicated
237  *               by returning negative values.
238  *
239  * Caller is responsible for halting CPU as needed, such as when
240  * overwriting a second stage loader.
241  */
242 static int parse_ihex(FILE *image, void *context,
243         bool (*is_external)(uint32_t addr, size_t len),
244         int (*poke) (void *context, uint32_t addr, bool external,
245         const unsigned char *data, size_t len))
246 {
247         unsigned char data[1023];
248         uint32_t data_addr = 0;
249         size_t data_len = 0;
250         int rc;
251         int first_line = 1;
252         bool external = false;
253
254         /* Read the input file as an IHEX file, and report the memory segments
255          * as we go.  Each line holds a max of 16 bytes, but uploading is
256          * faster (and EEPROM space smaller) if we merge those lines into larger
257          * chunks.  Most hex files keep memory segments together, which makes
258          * such merging all but free.  (But it may still be worth sorting the
259          * hex files to make up for undesirable behavior from tools.)
260          *
261          * Note that EEPROM segments max out at 1023 bytes; the upload protocol
262          * allows segments of up to 64 KBytes (more than a loader could handle).
263          */
264         for (;;) {
265                 char buf[512], *cp;
266                 char tmp, type;
267                 size_t len;
268                 unsigned idx, off;
269
270                 cp = fgets(buf, sizeof(buf), image);
271                 if (cp == NULL) {
272                         logerror("EOF without EOF record!\n");
273                         break;
274                 }
275
276                 /* EXTENSION: "# comment-till-end-of-line", for copyrights etc */
277                 if (buf[0] == '#')
278                         continue;
279
280                 if (buf[0] != ':') {
281                         logerror("not an ihex record: %s", buf);
282                         return -2;
283                 }
284
285                 /* ignore any newline */
286                 cp = strchr(buf, '\n');
287                 if (cp)
288                         *cp = 0;
289
290                 if (verbose >= 3)
291                         logerror("** LINE: %s\n", buf);
292
293                 /* Read the length field (up to 16 bytes) */
294                 tmp = buf[3];
295                 buf[3] = 0;
296                 len = strtoul(buf+1, NULL, 16);
297                 buf[3] = tmp;
298
299                 /* Read the target offset (address up to 64KB) */
300                 tmp = buf[7];
301                 buf[7] = 0;
302                 off = (int)strtoul(buf+3, NULL, 16);
303                 buf[7] = tmp;
304
305                 /* Initialize data_addr */
306                 if (first_line) {
307                         data_addr = off;
308                         first_line = 0;
309                 }
310
311                 /* Read the record type */
312                 tmp = buf[9];
313                 buf[9] = 0;
314                 type = (char)strtoul(buf+7, NULL, 16);
315                 buf[9] = tmp;
316
317                 /* If this is an EOF record, then make it so. */
318                 if (type == 1) {
319                         if (verbose >= 2)
320                                 logerror("EOF on hexfile\n");
321                         break;
322                 }
323
324                 if (type != 0) {
325                         logerror("unsupported record type: %u\n", type);
326                         return -3;
327                 }
328
329                 if ((len * 2) + 11 > strlen(buf)) {
330                         logerror("record too short?\n");
331                         return -4;
332                 }
333
334                 /* FIXME check for _physically_ contiguous not just virtually
335                  * e.g. on FX2 0x1f00-0x2100 includes both on-chip and external
336                  * memory so it's not really contiguous */
337
338                 /* flush the saved data if it's not contiguous,
339                 * or when we've buffered as much as we can.
340                 */
341                 if (data_len != 0
342                         && (off != (data_addr + data_len)
343                         /* || !merge */
344                         || (data_len + len) > sizeof(data))) {
345                                 if (is_external)
346                                         external = is_external(data_addr, data_len);
347                                 rc = poke(context, data_addr, external, data, data_len);
348                                 if (rc < 0)
349                                         return -1;
350                                 data_addr = off;
351                                 data_len = 0;
352                 }
353
354                 /* append to saved data, flush later */
355                 for (idx = 0, cp = buf+9 ;  idx < len ;  idx += 1, cp += 2) {
356                         tmp = cp[2];
357                         cp[2] = 0;
358                         data[data_len + idx] = (uint8_t)strtoul(cp, NULL, 16);
359                         cp[2] = tmp;
360                 }
361                 data_len += len;
362         }
363
364
365         /* flush any data remaining */
366         if (data_len != 0) {
367                 if (is_external)
368                         external = is_external(data_addr, data_len);
369                 rc = poke(context, data_addr, external, data, data_len);
370                 if (rc < 0)
371                         return -1;
372         }
373         return 0;
374 }
375
376 /*
377  * Parse a binary image file and write it as is to the target.
378  * Applies to Cypress BIX images for RAM or Cypress IIC images
379  * for EEPROM.
380  *
381  * image       - the BIX image file
382  * context     - for use by poke()
383  * is_external - if non-null, used to check which segments go into
384  *               external memory (writable only by software loader)
385  * poke        - called with each memory segment; errors indicated
386  *               by returning negative values.
387  *
388  * Caller is responsible for halting CPU as needed, such as when
389  * overwriting a second stage loader.
390  */
391 static int parse_bin(FILE *image, void *context,
392         bool (*is_external)(uint32_t addr, size_t len), int (*poke)(void *context,
393         uint32_t addr, bool external, const unsigned char *data, size_t len))
394 {
395         unsigned char data[4096];
396         uint32_t data_addr = 0;
397         size_t data_len = 0;
398         int rc;
399         bool external = false;
400
401         for (;;) {
402                 data_len = fread(data, 1, 4096, image);
403                 if (data_len == 0)
404                         break;
405                 if (is_external)
406                         external = is_external(data_addr, data_len);
407                 rc = poke(context, data_addr, external, data, data_len);
408                 if (rc < 0)
409                         return -1;
410                 data_addr += (uint32_t)data_len;
411         }
412         return feof(image)?0:-1;
413 }
414
415 /*
416  * Parse a Cypress IIC image file and invoke the poke() function on the
417  * various segments for writing to RAM
418  *
419  * image       - the IIC image file
420  * context     - for use by poke()
421  * is_external - if non-null, used to check which segments go into
422  *               external memory (writable only by software loader)
423  * poke        - called with each memory segment; errors indicated
424  *               by returning negative values.
425  *
426  * Caller is responsible for halting CPU as needed, such as when
427  * overwriting a second stage loader.
428  */
429 static int parse_iic(FILE *image, void *context,
430         bool (*is_external)(uint32_t addr, size_t len),
431         int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len))
432 {
433         unsigned char data[4096];
434         uint32_t data_addr = 0;
435         size_t data_len = 0, read_len;
436         uint8_t block_header[4];
437         int rc;
438         bool external = false;
439         long file_size, initial_pos;
440
441         initial_pos = ftell(image);
442         if (initial_pos < 0)
443                 return -1;
444
445         fseek(image, 0L, SEEK_END);
446         file_size = ftell(image);
447         fseek(image, initial_pos, SEEK_SET);
448         for (;;) {
449                 /* Ignore the trailing reset IIC data (5 bytes) */
450                 if (ftell(image) >= (file_size - 5))
451                         break;
452                 if (fread(&block_header, 1, sizeof(block_header), image) != 4) {
453                         logerror("unable to read IIC block header\n");
454                         return -1;
455                 }
456                 data_len = (block_header[0] << 8) + block_header[1];
457                 data_addr = (block_header[2] << 8) + block_header[3];
458                 if (data_len > sizeof(data)) {
459                         /* If this is ever reported as an error, switch to using malloc/realloc */
460                         logerror("IIC data block too small - please report this error to libusb.info\n");
461                         return -1;
462                 }
463                 read_len = fread(data, 1, data_len, image);
464                 if (read_len != data_len) {
465                         logerror("read error\n");
466                         return -1;
467                 }
468                 if (is_external)
469                         external = is_external(data_addr, data_len);
470                 rc = poke(context, data_addr, external, data, data_len);
471                 if (rc < 0)
472                         return -1;
473         }
474         return 0;
475 }
476
477 /* the parse call will be selected according to the image type */
478 static int (*parse[IMG_TYPE_MAX])(FILE *image, void *context, bool (*is_external)(uint32_t addr, size_t len),
479            int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len))
480            = { parse_ihex, parse_iic, parse_bin };
481
482 /*****************************************************************************/
483
484 /*
485  * For writing to RAM using a first (hardware) or second (software)
486  * stage loader and 0xA0 or 0xA3 vendor requests
487  */
488 typedef enum {
489         _undef = 0,
490         internal_only,          /* hardware first-stage loader */
491         skip_internal,          /* first phase, second-stage loader */
492         skip_external           /* second phase, second-stage loader */
493 } ram_mode;
494
495 struct ram_poke_context {
496         libusb_device_handle *device;
497         ram_mode mode;
498         size_t total, count;
499 };
500
501 #define RETRY_LIMIT 5
502
503 static int ram_poke(void *context, uint32_t addr, bool external,
504         const unsigned char *data, size_t len)
505 {
506         struct ram_poke_context *ctx = (struct ram_poke_context*)context;
507         int rc;
508         unsigned retry = 0;
509
510         switch (ctx->mode) {
511         case internal_only:             /* CPU should be stopped */
512                 if (external) {
513                         logerror("can't write %u bytes external memory at 0x%08x\n",
514                                 (unsigned)len, addr);
515                         return -EINVAL;
516                 }
517                 break;
518         case skip_internal:             /* CPU must be running */
519                 if (!external) {
520                         if (verbose >= 2) {
521                                 logerror("SKIP on-chip RAM, %u bytes at 0x%08x\n",
522                                         (unsigned)len, addr);
523                         }
524                         return 0;
525                 }
526                 break;
527         case skip_external:             /* CPU should be stopped */
528                 if (external) {
529                         if (verbose >= 2) {
530                                 logerror("SKIP external RAM, %u bytes at 0x%08x\n",
531                                         (unsigned)len, addr);
532                         }
533                         return 0;
534                 }
535                 break;
536         case _undef:
537         default:
538                 logerror("bug\n");
539                 return -EDOM;
540         }
541
542         ctx->total += len;
543         ctx->count++;
544
545         /* Retry this till we get a real error. Control messages are not
546          * NAKed (just dropped) so time out means is a real problem.
547          */
548         while ((rc = ezusb_write(ctx->device,
549                 external ? "write external" : "write on-chip",
550                 external ? RW_MEMORY : RW_INTERNAL,
551                 addr, data, len)) < 0
552                 && retry < RETRY_LIMIT) {
553                 if (rc != LIBUSB_ERROR_TIMEOUT)
554                         break;
555                 retry += 1;
556         }
557         return rc;
558 }
559
560 /*
561  * Load a Cypress Image file into target RAM.
562  * See http://www.cypress.com/?docID=41351 (AN76405 PDF) for more info.
563  */
564 static int fx3_load_ram(libusb_device_handle *device, const char *path)
565 {
566         uint32_t dCheckSum, dExpectedCheckSum, dAddress, i, dLen, dLength;
567         uint32_t* dImageBuf;
568         unsigned char *bBuf, hBuf[4], blBuf[4], rBuf[4096];
569         FILE *image;
570         int ret = 0;
571
572         image = fopen(path, "rb");
573         if (image == NULL) {
574                 logerror("unable to open '%s' for input\n", path);
575                 return -2;
576         } else if (verbose)
577                 logerror("open firmware image %s for RAM upload\n", path);
578
579         // Read header
580         if (fread(hBuf, sizeof(char), sizeof(hBuf), image) != sizeof(hBuf)) {
581                 logerror("could not read image header");
582                 ret = -3;
583                 goto exit;
584         }
585
586         // check "CY" signature byte and format
587         if ((hBuf[0] != 'C') || (hBuf[1] != 'Y')) {
588                 logerror("image doesn't have a CYpress signature\n");
589                 ret = -3;
590                 goto exit;
591         }
592
593         // Check bImageType
594         switch(hBuf[3]) {
595         case 0xB0:
596                 if (verbose)
597                         logerror("normal FW binary %s image with checksum\n", (hBuf[2]&0x01)?"data":"executable");
598                 break;
599         case 0xB1:
600                 logerror("security binary image is not currently supported\n");
601                 ret = -3;
602                 goto exit;
603         case 0xB2:
604                 logerror("VID:PID image is not currently supported\n");
605                 ret = -3;
606                 goto exit;
607         default:
608                 logerror("invalid image type 0x%02X\n", hBuf[3]);
609                 ret = -3;
610                 goto exit;
611         }
612
613         // Read the bootloader version
614         if (verbose) {
615                 if ((ezusb_read(device, "read bootloader version", RW_INTERNAL, 0xFFFF0020, blBuf, 4) < 0)) {
616                         logerror("Could not read bootloader version\n");
617                         ret = -8;
618                         goto exit;
619                 }
620                 logerror("FX3 bootloader version: 0x%02X%02X%02X%02X\n", blBuf[3], blBuf[2], blBuf[1], blBuf[0]);
621         }
622
623         dCheckSum = 0;
624         if (verbose)
625                 logerror("writing image...\n");
626         while (1) {
627                 if ((fread(&dLength, sizeof(uint32_t), 1, image) != 1) ||  // read dLength
628                         (fread(&dAddress, sizeof(uint32_t), 1, image) != 1)) { // read dAddress
629                         logerror("could not read image");
630                         ret = -3;
631                         goto exit;
632                 }
633                 if (dLength == 0)
634                         break; // done
635
636                 dImageBuf = calloc(dLength, sizeof(uint32_t));
637                 if (dImageBuf == NULL) {
638                         logerror("could not allocate buffer for image chunk\n");
639                         ret = -4;
640                         goto exit;
641                 }
642
643                 // read sections
644                 if (fread(dImageBuf, sizeof(uint32_t), dLength, image) != dLength) {
645                         logerror("could not read image");
646                         free(dImageBuf);
647                         ret = -3;
648                         goto exit;
649                 }
650                 for (i = 0; i < dLength; i++)
651                         dCheckSum += dImageBuf[i];
652                 dLength <<= 2; // convert to Byte length
653                 bBuf = (unsigned char*) dImageBuf;
654
655                 while (dLength > 0) {
656                         dLen = 4096; // 4K max
657                         if (dLen > dLength)
658                                 dLen = dLength;
659                         if ((ezusb_write(device, "write firmware", RW_INTERNAL, dAddress, bBuf, dLen) < 0) ||
660                                 (ezusb_read(device, "read firmware", RW_INTERNAL, dAddress, rBuf, dLen) < 0)) {
661                                 logerror("R/W error\n");
662                                 free(dImageBuf);
663                                 ret = -5;
664                                 goto exit;
665                         }
666                         // Verify data: rBuf with bBuf
667                         for (i = 0; i < dLen; i++) {
668                                 if (rBuf[i] != bBuf[i]) {
669                                         logerror("verify error");
670                                         free(dImageBuf);
671                                         ret = -6;
672                                         goto exit;
673                                 }
674                         }
675
676                         dLength -= dLen;
677                         bBuf += dLen;
678                         dAddress += dLen;
679                 }
680                 free(dImageBuf);
681         }
682
683         // read pre-computed checksum data
684         if ((fread(&dExpectedCheckSum, sizeof(uint32_t), 1, image) != 1) ||
685                 (dCheckSum != dExpectedCheckSum)) {
686                 logerror("checksum error\n");
687                 ret = -7;
688                 goto exit;
689         }
690
691         // transfer execution to Program Entry
692         if (!ezusb_fx3_jump(device, dAddress)) {
693                 ret = -6;
694         }
695
696 exit:
697         fclose(image);
698         return ret;
699 }
700
701 /*
702  * Load a firmware file into target RAM. device is the open libusb
703  * device, and the path is the name of the source file. Open the file,
704  * parse the bytes, and write them in one or two phases.
705  *
706  * If stage == 0, this uses the first stage loader, built into EZ-USB
707  * hardware but limited to writing on-chip memory or CPUCS.  Everything
708  * is written during one stage, unless there's an error such as the image
709  * holding data that needs to be written to external memory.
710  *
711  * Otherwise, things are written in two stages.  First the external
712  * memory is written, expecting a second stage loader to have already
713  * been loaded.  Then file is re-parsed and on-chip memory is written.
714  */
715 int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, int img_type, int stage)
716 {
717         FILE *image;
718         uint32_t cpucs_addr;
719         bool (*is_external)(uint32_t off, size_t len);
720         struct ram_poke_context ctx;
721         int status;
722         uint8_t iic_header[8] = { 0 };
723         int ret = 0;
724
725         if (fx_type == FX_TYPE_FX3)
726                 return fx3_load_ram(device, path);
727
728         image = fopen(path, "rb");
729         if (image == NULL) {
730                 logerror("%s: unable to open for input.\n", path);
731                 return -2;
732         } else if (verbose > 1)
733                 logerror("open firmware image %s for RAM upload\n", path);
734
735         if (img_type == IMG_TYPE_IIC) {
736                 if ( (fread(iic_header, 1, sizeof(iic_header), image) != sizeof(iic_header))
737                   || (((fx_type == FX_TYPE_FX2LP) || (fx_type == FX_TYPE_FX2)) && (iic_header[0] != 0xC2))
738                   || ((fx_type == FX_TYPE_AN21) && (iic_header[0] != 0xB2))
739                   || ((fx_type == FX_TYPE_FX1) && (iic_header[0] != 0xB6)) ) {
740                         logerror("IIC image does not contain executable code - cannot load to RAM.\n");
741                         ret = -1;
742                         goto exit;
743                 }
744         }
745
746         /* EZ-USB original/FX and FX2 devices differ, apart from the 8051 core */
747         switch(fx_type) {
748         case FX_TYPE_FX2LP:
749                 cpucs_addr = 0xe600;
750                 is_external = fx2lp_is_external;
751                 break;
752         case FX_TYPE_FX2:
753                 cpucs_addr = 0xe600;
754                 is_external = fx2_is_external;
755                 break;
756         default:
757                 cpucs_addr = 0x7f92;
758                 is_external = fx_is_external;
759                 break;
760         }
761
762         /* use only first stage loader? */
763         if (stage == 0) {
764                 ctx.mode = internal_only;
765
766                 /* if required, halt the CPU while we overwrite its code/data */
767                 if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
768                 {
769                         ret = -1;
770                         goto exit;
771                 }
772
773                 /* 2nd stage, first part? loader was already uploaded */
774         } else {
775                 ctx.mode = skip_internal;
776
777                 /* let CPU run; overwrite the 2nd stage loader later */
778                 if (verbose)
779                         logerror("2nd stage: write external memory\n");
780         }
781
782         /* scan the image, first (maybe only) time */
783         ctx.device = device;
784         ctx.total = ctx.count = 0;
785         status = parse[img_type](image, &ctx, is_external, ram_poke);
786         if (status < 0) {
787                 logerror("unable to upload %s\n", path);
788                 ret = status;
789                 goto exit;
790         }
791
792         /* second part of 2nd stage: rescan */
793         // TODO: what should we do for non HEX images there?
794         if (stage) {
795                 ctx.mode = skip_external;
796
797                 /* if needed, halt the CPU while we overwrite the 1st stage loader */
798                 if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
799                 {
800                         ret = -1;
801                         goto exit;
802                 }
803
804                 /* at least write the interrupt vectors (at 0x0000) for reset! */
805                 rewind(image);
806                 if (verbose)
807                         logerror("2nd stage: write on-chip memory\n");
808                 status = parse_ihex(image, &ctx, is_external, ram_poke);
809                 if (status < 0) {
810                         logerror("unable to completely upload %s\n", path);
811                         ret = status;
812                         goto exit;
813                 }
814         }
815
816         if (verbose)
817                 logerror("... WROTE: %d bytes, %d segments, avg %d\n",
818                 (int)ctx.total, (int)ctx.count, (int)(ctx.total/ctx.count));
819
820         /* if required, reset the CPU so it runs what we just uploaded */
821         if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, true))
822                 ret = -1;
823
824 exit:
825         fclose(image);
826         return ret;
827 }