libusb 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +8 -2
- data/Gemfile +2 -0
- data/History.md +12 -0
- data/README.md +25 -14
- data/Rakefile +64 -109
- data/appveyor.yml +23 -0
- data/ext/extconf.rb +10 -12
- data/ext/libusb_recipe.rb +29 -0
- data/lib/libusb/call.rb +14 -11
- data/lib/libusb/compat.rb +9 -9
- data/lib/libusb/context.rb +16 -1
- data/lib/libusb/dependencies.rb +7 -0
- data/lib/libusb/dev_handle.rb +13 -3
- data/lib/libusb/eventmachine.rb +4 -4
- data/lib/libusb/transfer.rb +71 -10
- data/lib/libusb/version_gem.rb +1 -1
- data/libusb.gemspec +7 -5
- data/ports/archives/libusb-1.0.21.tar.bz2 +0 -0
- data/test/test_libusb_bulk_stream_transfer.rb +1 -1
- data/test/test_libusb_descriptors.rb +4 -4
- data/test/test_libusb_event_machine.rb +7 -7
- data/test/test_libusb_hotplug.rb +15 -3
- data/test/test_libusb_iso_transfer.rb +1 -1
- data/test/test_libusb_mass_storage.rb +19 -19
- data/test/test_libusb_mass_storage2.rb +1 -1
- data/test/test_libusb_structs.rb +13 -0
- data/test/test_libusb_threads.rb +2 -2
- data/wireshark-usb-sniffer.png +0 -0
- metadata +32 -156
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ext/libusb-1.0.20/AUTHORS +0 -89
- data/ext/libusb-1.0.20/COPYING +0 -504
- data/ext/libusb-1.0.20/ChangeLog +0 -227
- data/ext/libusb-1.0.20/INSTALL +0 -234
- data/ext/libusb-1.0.20/Makefile.am +0 -28
- data/ext/libusb-1.0.20/Makefile.in +0 -897
- data/ext/libusb-1.0.20/NEWS +0 -2
- data/ext/libusb-1.0.20/PORTING +0 -94
- data/ext/libusb-1.0.20/README +0 -29
- data/ext/libusb-1.0.20/TODO +0 -2
- data/ext/libusb-1.0.20/Xcode/common.xcconfig +0 -49
- data/ext/libusb-1.0.20/Xcode/config.h +0 -28
- data/ext/libusb-1.0.20/Xcode/debug.xcconfig +0 -29
- data/ext/libusb-1.0.20/Xcode/libusb.xcconfig +0 -21
- data/ext/libusb-1.0.20/Xcode/libusb.xcodeproj/project.pbxproj +0 -865
- data/ext/libusb-1.0.20/Xcode/libusb_debug.xcconfig +0 -21
- data/ext/libusb-1.0.20/Xcode/libusb_release.xcconfig +0 -21
- data/ext/libusb-1.0.20/Xcode/release.xcconfig +0 -30
- data/ext/libusb-1.0.20/aclocal.m4 +0 -1193
- data/ext/libusb-1.0.20/android/README +0 -114
- data/ext/libusb-1.0.20/android/config.h +0 -81
- data/ext/libusb-1.0.20/android/jni/Android.mk +0 -23
- data/ext/libusb-1.0.20/android/jni/Application.mk +0 -24
- data/ext/libusb-1.0.20/android/jni/examples.mk +0 -134
- data/ext/libusb-1.0.20/android/jni/libusb.mk +0 -54
- data/ext/libusb-1.0.20/android/jni/tests.mk +0 -56
- data/ext/libusb-1.0.20/compile +0 -347
- data/ext/libusb-1.0.20/config.guess +0 -1421
- data/ext/libusb-1.0.20/config.h.in +0 -155
- data/ext/libusb-1.0.20/config.sub +0 -1807
- data/ext/libusb-1.0.20/configure +0 -15466
- data/ext/libusb-1.0.20/configure.ac +0 -326
- data/ext/libusb-1.0.20/depcomp +0 -791
- data/ext/libusb-1.0.20/doc/Makefile.am +0 -9
- data/ext/libusb-1.0.20/doc/Makefile.in +0 -456
- data/ext/libusb-1.0.20/doc/doxygen.cfg.in +0 -2334
- data/ext/libusb-1.0.20/examples/Makefile.am +0 -19
- data/ext/libusb-1.0.20/examples/Makefile.in +0 -713
- data/ext/libusb-1.0.20/examples/dpfp.c +0 -506
- data/ext/libusb-1.0.20/examples/dpfp_threaded.c +0 -549
- data/ext/libusb-1.0.20/examples/ezusb.c +0 -831
- data/ext/libusb-1.0.20/examples/ezusb.h +0 -120
- data/ext/libusb-1.0.20/examples/fxload.c +0 -308
- data/ext/libusb-1.0.20/examples/getopt/getopt.c +0 -1060
- data/ext/libusb-1.0.20/examples/getopt/getopt.h +0 -180
- data/ext/libusb-1.0.20/examples/getopt/getopt1.c +0 -188
- data/ext/libusb-1.0.20/examples/hotplugtest.c +0 -122
- data/ext/libusb-1.0.20/examples/listdevs.c +0 -71
- data/ext/libusb-1.0.20/examples/sam3u_benchmark.c +0 -193
- data/ext/libusb-1.0.20/examples/xusb.c +0 -1130
- data/ext/libusb-1.0.20/install-sh +0 -501
- data/ext/libusb-1.0.20/libusb-1.0.pc.in +0 -11
- data/ext/libusb-1.0.20/libusb/Makefile.am +0 -90
- data/ext/libusb-1.0.20/libusb/Makefile.in +0 -1053
- data/ext/libusb-1.0.20/libusb/core.c +0 -2452
- data/ext/libusb-1.0.20/libusb/descriptor.c +0 -1201
- data/ext/libusb-1.0.20/libusb/hotplug.c +0 -344
- data/ext/libusb-1.0.20/libusb/hotplug.h +0 -90
- data/ext/libusb-1.0.20/libusb/io.c +0 -2760
- data/ext/libusb-1.0.20/libusb/libusb-1.0.def +0 -168
- data/ext/libusb-1.0.20/libusb/libusb-1.0.rc +0 -61
- data/ext/libusb-1.0.20/libusb/libusb.h +0 -1999
- data/ext/libusb-1.0.20/libusb/libusbi.h +0 -1102
- data/ext/libusb-1.0.20/libusb/os/darwin_usb.c +0 -1969
- data/ext/libusb-1.0.20/libusb/os/darwin_usb.h +0 -158
- data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.am +0 -5
- data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.in +0 -810
- data/ext/libusb-1.0.20/libusb/os/haiku/aclocal.m4 +0 -1193
- data/ext/libusb-1.0.20/libusb/os/haiku/compile +0 -347
- data/ext/libusb-1.0.20/libusb/os/haiku/config.guess +0 -1421
- data/ext/libusb-1.0.20/libusb/os/haiku/config.sub +0 -1807
- data/ext/libusb-1.0.20/libusb/os/haiku/configure +0 -17579
- data/ext/libusb-1.0.20/libusb/os/haiku/configure.ac +0 -8
- data/ext/libusb-1.0.20/libusb/os/haiku/depcomp +0 -791
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_pollfs.cpp +0 -378
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb.h +0 -112
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_backend.cpp +0 -550
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.cpp +0 -255
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.h +0 -180
- data/ext/libusb-1.0.20/libusb/os/haiku/install-sh +0 -501
- data/ext/libusb-1.0.20/libusb/os/haiku/ltmain.sh +0 -9655
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/libtool.m4 +0 -7992
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltoptions.m4 +0 -384
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltsugar.m4 +0 -123
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/ltversion.m4 +0 -23
- data/ext/libusb-1.0.20/libusb/os/haiku/m4/lt~obsolete.m4 +0 -98
- data/ext/libusb-1.0.20/libusb/os/haiku/missing +0 -215
- data/ext/libusb-1.0.20/libusb/os/linux_netlink.c +0 -369
- data/ext/libusb-1.0.20/libusb/os/linux_udev.c +0 -306
- data/ext/libusb-1.0.20/libusb/os/linux_usbfs.c +0 -2692
- data/ext/libusb-1.0.20/libusb/os/linux_usbfs.h +0 -192
- data/ext/libusb-1.0.20/libusb/os/netbsd_usb.c +0 -674
- data/ext/libusb-1.0.20/libusb/os/openbsd_usb.c +0 -768
- data/ext/libusb-1.0.20/libusb/os/poll_posix.c +0 -53
- data/ext/libusb-1.0.20/libusb/os/poll_posix.h +0 -11
- data/ext/libusb-1.0.20/libusb/os/poll_windows.c +0 -728
- data/ext/libusb-1.0.20/libusb/os/poll_windows.h +0 -131
- data/ext/libusb-1.0.20/libusb/os/threads_posix.c +0 -82
- data/ext/libusb-1.0.20/libusb/os/threads_posix.h +0 -50
- data/ext/libusb-1.0.20/libusb/os/threads_windows.c +0 -214
- data/ext/libusb-1.0.20/libusb/os/threads_windows.h +0 -87
- data/ext/libusb-1.0.20/libusb/os/wince_usb.c +0 -869
- data/ext/libusb-1.0.20/libusb/os/wince_usb.h +0 -131
- data/ext/libusb-1.0.20/libusb/os/windows_common.h +0 -108
- data/ext/libusb-1.0.20/libusb/os/windows_usb.c +0 -4643
- data/ext/libusb-1.0.20/libusb/os/windows_usb.h +0 -973
- data/ext/libusb-1.0.20/libusb/strerror.c +0 -202
- data/ext/libusb-1.0.20/libusb/sync.c +0 -308
- data/ext/libusb-1.0.20/libusb/version.h +0 -18
- data/ext/libusb-1.0.20/libusb/version_nano.h +0 -1
- data/ext/libusb-1.0.20/ltmain.sh +0 -9655
- data/ext/libusb-1.0.20/m4/libtool.m4 +0 -7992
- data/ext/libusb-1.0.20/m4/ltoptions.m4 +0 -384
- data/ext/libusb-1.0.20/m4/ltsugar.m4 +0 -123
- data/ext/libusb-1.0.20/m4/ltversion.m4 +0 -23
- data/ext/libusb-1.0.20/m4/lt~obsolete.m4 +0 -98
- data/ext/libusb-1.0.20/missing +0 -215
- data/ext/libusb-1.0.20/tests/Makefile.am +0 -6
- data/ext/libusb-1.0.20/tests/Makefile.in +0 -596
- data/ext/libusb-1.0.20/tests/libusb_testlib.h +0 -107
- data/ext/libusb-1.0.20/tests/stress.c +0 -160
- data/ext/libusb-1.0.20/tests/testlib.c +0 -277
- metadata.gz.sig +0 -0
|
@@ -1,831 +0,0 @@
|
|
|
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
|
-
if (fseek(image, 0L, SEEK_END) != 0)
|
|
446
|
-
return -1;
|
|
447
|
-
file_size = ftell(image);
|
|
448
|
-
if (fseek(image, initial_pos, SEEK_SET) != 0)
|
|
449
|
-
return -1;
|
|
450
|
-
for (;;) {
|
|
451
|
-
/* Ignore the trailing reset IIC data (5 bytes) */
|
|
452
|
-
if (ftell(image) >= (file_size - 5))
|
|
453
|
-
break;
|
|
454
|
-
if (fread(&block_header, 1, sizeof(block_header), image) != 4) {
|
|
455
|
-
logerror("unable to read IIC block header\n");
|
|
456
|
-
return -1;
|
|
457
|
-
}
|
|
458
|
-
data_len = (block_header[0] << 8) + block_header[1];
|
|
459
|
-
data_addr = (block_header[2] << 8) + block_header[3];
|
|
460
|
-
if (data_len > sizeof(data)) {
|
|
461
|
-
/* If this is ever reported as an error, switch to using malloc/realloc */
|
|
462
|
-
logerror("IIC data block too small - please report this error to libusb.info\n");
|
|
463
|
-
return -1;
|
|
464
|
-
}
|
|
465
|
-
read_len = fread(data, 1, data_len, image);
|
|
466
|
-
if (read_len != data_len) {
|
|
467
|
-
logerror("read error\n");
|
|
468
|
-
return -1;
|
|
469
|
-
}
|
|
470
|
-
if (is_external)
|
|
471
|
-
external = is_external(data_addr, data_len);
|
|
472
|
-
rc = poke(context, data_addr, external, data, data_len);
|
|
473
|
-
if (rc < 0)
|
|
474
|
-
return -1;
|
|
475
|
-
}
|
|
476
|
-
return 0;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/* the parse call will be selected according to the image type */
|
|
480
|
-
static int (*parse[IMG_TYPE_MAX])(FILE *image, void *context, bool (*is_external)(uint32_t addr, size_t len),
|
|
481
|
-
int (*poke)(void *context, uint32_t addr, bool external, const unsigned char *data, size_t len))
|
|
482
|
-
= { parse_ihex, parse_iic, parse_bin };
|
|
483
|
-
|
|
484
|
-
/*****************************************************************************/
|
|
485
|
-
|
|
486
|
-
/*
|
|
487
|
-
* For writing to RAM using a first (hardware) or second (software)
|
|
488
|
-
* stage loader and 0xA0 or 0xA3 vendor requests
|
|
489
|
-
*/
|
|
490
|
-
typedef enum {
|
|
491
|
-
_undef = 0,
|
|
492
|
-
internal_only, /* hardware first-stage loader */
|
|
493
|
-
skip_internal, /* first phase, second-stage loader */
|
|
494
|
-
skip_external /* second phase, second-stage loader */
|
|
495
|
-
} ram_mode;
|
|
496
|
-
|
|
497
|
-
struct ram_poke_context {
|
|
498
|
-
libusb_device_handle *device;
|
|
499
|
-
ram_mode mode;
|
|
500
|
-
size_t total, count;
|
|
501
|
-
};
|
|
502
|
-
|
|
503
|
-
#define RETRY_LIMIT 5
|
|
504
|
-
|
|
505
|
-
static int ram_poke(void *context, uint32_t addr, bool external,
|
|
506
|
-
const unsigned char *data, size_t len)
|
|
507
|
-
{
|
|
508
|
-
struct ram_poke_context *ctx = (struct ram_poke_context*)context;
|
|
509
|
-
int rc;
|
|
510
|
-
unsigned retry = 0;
|
|
511
|
-
|
|
512
|
-
switch (ctx->mode) {
|
|
513
|
-
case internal_only: /* CPU should be stopped */
|
|
514
|
-
if (external) {
|
|
515
|
-
logerror("can't write %u bytes external memory at 0x%08x\n",
|
|
516
|
-
(unsigned)len, addr);
|
|
517
|
-
return -EINVAL;
|
|
518
|
-
}
|
|
519
|
-
break;
|
|
520
|
-
case skip_internal: /* CPU must be running */
|
|
521
|
-
if (!external) {
|
|
522
|
-
if (verbose >= 2) {
|
|
523
|
-
logerror("SKIP on-chip RAM, %u bytes at 0x%08x\n",
|
|
524
|
-
(unsigned)len, addr);
|
|
525
|
-
}
|
|
526
|
-
return 0;
|
|
527
|
-
}
|
|
528
|
-
break;
|
|
529
|
-
case skip_external: /* CPU should be stopped */
|
|
530
|
-
if (external) {
|
|
531
|
-
if (verbose >= 2) {
|
|
532
|
-
logerror("SKIP external RAM, %u bytes at 0x%08x\n",
|
|
533
|
-
(unsigned)len, addr);
|
|
534
|
-
}
|
|
535
|
-
return 0;
|
|
536
|
-
}
|
|
537
|
-
break;
|
|
538
|
-
case _undef:
|
|
539
|
-
default:
|
|
540
|
-
logerror("bug\n");
|
|
541
|
-
return -EDOM;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
ctx->total += len;
|
|
545
|
-
ctx->count++;
|
|
546
|
-
|
|
547
|
-
/* Retry this till we get a real error. Control messages are not
|
|
548
|
-
* NAKed (just dropped) so time out means is a real problem.
|
|
549
|
-
*/
|
|
550
|
-
while ((rc = ezusb_write(ctx->device,
|
|
551
|
-
external ? "write external" : "write on-chip",
|
|
552
|
-
external ? RW_MEMORY : RW_INTERNAL,
|
|
553
|
-
addr, data, len)) < 0
|
|
554
|
-
&& retry < RETRY_LIMIT) {
|
|
555
|
-
if (rc != LIBUSB_ERROR_TIMEOUT)
|
|
556
|
-
break;
|
|
557
|
-
retry += 1;
|
|
558
|
-
}
|
|
559
|
-
return rc;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/*
|
|
563
|
-
* Load a Cypress Image file into target RAM.
|
|
564
|
-
* See http://www.cypress.com/?docID=41351 (AN76405 PDF) for more info.
|
|
565
|
-
*/
|
|
566
|
-
static int fx3_load_ram(libusb_device_handle *device, const char *path)
|
|
567
|
-
{
|
|
568
|
-
uint32_t dCheckSum, dExpectedCheckSum, dAddress, i, dLen, dLength;
|
|
569
|
-
uint32_t* dImageBuf;
|
|
570
|
-
unsigned char *bBuf, hBuf[4], blBuf[4], rBuf[4096];
|
|
571
|
-
FILE *image;
|
|
572
|
-
int ret = 0;
|
|
573
|
-
|
|
574
|
-
image = fopen(path, "rb");
|
|
575
|
-
if (image == NULL) {
|
|
576
|
-
logerror("unable to open '%s' for input\n", path);
|
|
577
|
-
return -2;
|
|
578
|
-
} else if (verbose)
|
|
579
|
-
logerror("open firmware image %s for RAM upload\n", path);
|
|
580
|
-
|
|
581
|
-
// Read header
|
|
582
|
-
if (fread(hBuf, sizeof(char), sizeof(hBuf), image) != sizeof(hBuf)) {
|
|
583
|
-
logerror("could not read image header");
|
|
584
|
-
ret = -3;
|
|
585
|
-
goto exit;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
// check "CY" signature byte and format
|
|
589
|
-
if ((hBuf[0] != 'C') || (hBuf[1] != 'Y')) {
|
|
590
|
-
logerror("image doesn't have a CYpress signature\n");
|
|
591
|
-
ret = -3;
|
|
592
|
-
goto exit;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// Check bImageType
|
|
596
|
-
switch(hBuf[3]) {
|
|
597
|
-
case 0xB0:
|
|
598
|
-
if (verbose)
|
|
599
|
-
logerror("normal FW binary %s image with checksum\n", (hBuf[2]&0x01)?"data":"executable");
|
|
600
|
-
break;
|
|
601
|
-
case 0xB1:
|
|
602
|
-
logerror("security binary image is not currently supported\n");
|
|
603
|
-
ret = -3;
|
|
604
|
-
goto exit;
|
|
605
|
-
case 0xB2:
|
|
606
|
-
logerror("VID:PID image is not currently supported\n");
|
|
607
|
-
ret = -3;
|
|
608
|
-
goto exit;
|
|
609
|
-
default:
|
|
610
|
-
logerror("invalid image type 0x%02X\n", hBuf[3]);
|
|
611
|
-
ret = -3;
|
|
612
|
-
goto exit;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
// Read the bootloader version
|
|
616
|
-
if (verbose) {
|
|
617
|
-
if ((ezusb_read(device, "read bootloader version", RW_INTERNAL, 0xFFFF0020, blBuf, 4) < 0)) {
|
|
618
|
-
logerror("Could not read bootloader version\n");
|
|
619
|
-
ret = -8;
|
|
620
|
-
goto exit;
|
|
621
|
-
}
|
|
622
|
-
logerror("FX3 bootloader version: 0x%02X%02X%02X%02X\n", blBuf[3], blBuf[2], blBuf[1], blBuf[0]);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
dCheckSum = 0;
|
|
626
|
-
if (verbose)
|
|
627
|
-
logerror("writing image...\n");
|
|
628
|
-
while (1) {
|
|
629
|
-
if ((fread(&dLength, sizeof(uint32_t), 1, image) != 1) || // read dLength
|
|
630
|
-
(fread(&dAddress, sizeof(uint32_t), 1, image) != 1)) { // read dAddress
|
|
631
|
-
logerror("could not read image");
|
|
632
|
-
ret = -3;
|
|
633
|
-
goto exit;
|
|
634
|
-
}
|
|
635
|
-
if (dLength == 0)
|
|
636
|
-
break; // done
|
|
637
|
-
|
|
638
|
-
// coverity[tainted_data]
|
|
639
|
-
dImageBuf = (uint32_t*)calloc(dLength, sizeof(uint32_t));
|
|
640
|
-
if (dImageBuf == NULL) {
|
|
641
|
-
logerror("could not allocate buffer for image chunk\n");
|
|
642
|
-
ret = -4;
|
|
643
|
-
goto exit;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
// read sections
|
|
647
|
-
if (fread(dImageBuf, sizeof(uint32_t), dLength, image) != dLength) {
|
|
648
|
-
logerror("could not read image");
|
|
649
|
-
free(dImageBuf);
|
|
650
|
-
ret = -3;
|
|
651
|
-
goto exit;
|
|
652
|
-
}
|
|
653
|
-
for (i = 0; i < dLength; i++)
|
|
654
|
-
dCheckSum += dImageBuf[i];
|
|
655
|
-
dLength <<= 2; // convert to Byte length
|
|
656
|
-
bBuf = (unsigned char*) dImageBuf;
|
|
657
|
-
|
|
658
|
-
while (dLength > 0) {
|
|
659
|
-
dLen = 4096; // 4K max
|
|
660
|
-
if (dLen > dLength)
|
|
661
|
-
dLen = dLength;
|
|
662
|
-
if ((ezusb_write(device, "write firmware", RW_INTERNAL, dAddress, bBuf, dLen) < 0) ||
|
|
663
|
-
(ezusb_read(device, "read firmware", RW_INTERNAL, dAddress, rBuf, dLen) < 0)) {
|
|
664
|
-
logerror("R/W error\n");
|
|
665
|
-
free(dImageBuf);
|
|
666
|
-
ret = -5;
|
|
667
|
-
goto exit;
|
|
668
|
-
}
|
|
669
|
-
// Verify data: rBuf with bBuf
|
|
670
|
-
for (i = 0; i < dLen; i++) {
|
|
671
|
-
if (rBuf[i] != bBuf[i]) {
|
|
672
|
-
logerror("verify error");
|
|
673
|
-
free(dImageBuf);
|
|
674
|
-
ret = -6;
|
|
675
|
-
goto exit;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
dLength -= dLen;
|
|
680
|
-
bBuf += dLen;
|
|
681
|
-
dAddress += dLen;
|
|
682
|
-
}
|
|
683
|
-
free(dImageBuf);
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
// read pre-computed checksum data
|
|
687
|
-
if ((fread(&dExpectedCheckSum, sizeof(uint32_t), 1, image) != 1) ||
|
|
688
|
-
(dCheckSum != dExpectedCheckSum)) {
|
|
689
|
-
logerror("checksum error\n");
|
|
690
|
-
ret = -7;
|
|
691
|
-
goto exit;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
// transfer execution to Program Entry
|
|
695
|
-
if (!ezusb_fx3_jump(device, dAddress)) {
|
|
696
|
-
ret = -6;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
exit:
|
|
700
|
-
fclose(image);
|
|
701
|
-
return ret;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
/*
|
|
705
|
-
* Load a firmware file into target RAM. device is the open libusb
|
|
706
|
-
* device, and the path is the name of the source file. Open the file,
|
|
707
|
-
* parse the bytes, and write them in one or two phases.
|
|
708
|
-
*
|
|
709
|
-
* If stage == 0, this uses the first stage loader, built into EZ-USB
|
|
710
|
-
* hardware but limited to writing on-chip memory or CPUCS. Everything
|
|
711
|
-
* is written during one stage, unless there's an error such as the image
|
|
712
|
-
* holding data that needs to be written to external memory.
|
|
713
|
-
*
|
|
714
|
-
* Otherwise, things are written in two stages. First the external
|
|
715
|
-
* memory is written, expecting a second stage loader to have already
|
|
716
|
-
* been loaded. Then file is re-parsed and on-chip memory is written.
|
|
717
|
-
*/
|
|
718
|
-
int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, int img_type, int stage)
|
|
719
|
-
{
|
|
720
|
-
FILE *image;
|
|
721
|
-
uint32_t cpucs_addr;
|
|
722
|
-
bool (*is_external)(uint32_t off, size_t len);
|
|
723
|
-
struct ram_poke_context ctx;
|
|
724
|
-
int status;
|
|
725
|
-
uint8_t iic_header[8] = { 0 };
|
|
726
|
-
int ret = 0;
|
|
727
|
-
|
|
728
|
-
if (fx_type == FX_TYPE_FX3)
|
|
729
|
-
return fx3_load_ram(device, path);
|
|
730
|
-
|
|
731
|
-
image = fopen(path, "rb");
|
|
732
|
-
if (image == NULL) {
|
|
733
|
-
logerror("%s: unable to open for input.\n", path);
|
|
734
|
-
return -2;
|
|
735
|
-
} else if (verbose > 1)
|
|
736
|
-
logerror("open firmware image %s for RAM upload\n", path);
|
|
737
|
-
|
|
738
|
-
if (img_type == IMG_TYPE_IIC) {
|
|
739
|
-
if ( (fread(iic_header, 1, sizeof(iic_header), image) != sizeof(iic_header))
|
|
740
|
-
|| (((fx_type == FX_TYPE_FX2LP) || (fx_type == FX_TYPE_FX2)) && (iic_header[0] != 0xC2))
|
|
741
|
-
|| ((fx_type == FX_TYPE_AN21) && (iic_header[0] != 0xB2))
|
|
742
|
-
|| ((fx_type == FX_TYPE_FX1) && (iic_header[0] != 0xB6)) ) {
|
|
743
|
-
logerror("IIC image does not contain executable code - cannot load to RAM.\n");
|
|
744
|
-
ret = -1;
|
|
745
|
-
goto exit;
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
/* EZ-USB original/FX and FX2 devices differ, apart from the 8051 core */
|
|
750
|
-
switch(fx_type) {
|
|
751
|
-
case FX_TYPE_FX2LP:
|
|
752
|
-
cpucs_addr = 0xe600;
|
|
753
|
-
is_external = fx2lp_is_external;
|
|
754
|
-
break;
|
|
755
|
-
case FX_TYPE_FX2:
|
|
756
|
-
cpucs_addr = 0xe600;
|
|
757
|
-
is_external = fx2_is_external;
|
|
758
|
-
break;
|
|
759
|
-
default:
|
|
760
|
-
cpucs_addr = 0x7f92;
|
|
761
|
-
is_external = fx_is_external;
|
|
762
|
-
break;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
/* use only first stage loader? */
|
|
766
|
-
if (stage == 0) {
|
|
767
|
-
ctx.mode = internal_only;
|
|
768
|
-
|
|
769
|
-
/* if required, halt the CPU while we overwrite its code/data */
|
|
770
|
-
if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
|
|
771
|
-
{
|
|
772
|
-
ret = -1;
|
|
773
|
-
goto exit;
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
/* 2nd stage, first part? loader was already uploaded */
|
|
777
|
-
} else {
|
|
778
|
-
ctx.mode = skip_internal;
|
|
779
|
-
|
|
780
|
-
/* let CPU run; overwrite the 2nd stage loader later */
|
|
781
|
-
if (verbose)
|
|
782
|
-
logerror("2nd stage: write external memory\n");
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
/* scan the image, first (maybe only) time */
|
|
786
|
-
ctx.device = device;
|
|
787
|
-
ctx.total = ctx.count = 0;
|
|
788
|
-
status = parse[img_type](image, &ctx, is_external, ram_poke);
|
|
789
|
-
if (status < 0) {
|
|
790
|
-
logerror("unable to upload %s\n", path);
|
|
791
|
-
ret = status;
|
|
792
|
-
goto exit;
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
/* second part of 2nd stage: rescan */
|
|
796
|
-
// TODO: what should we do for non HEX images there?
|
|
797
|
-
if (stage) {
|
|
798
|
-
ctx.mode = skip_external;
|
|
799
|
-
|
|
800
|
-
/* if needed, halt the CPU while we overwrite the 1st stage loader */
|
|
801
|
-
if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
|
|
802
|
-
{
|
|
803
|
-
ret = -1;
|
|
804
|
-
goto exit;
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
/* at least write the interrupt vectors (at 0x0000) for reset! */
|
|
808
|
-
rewind(image);
|
|
809
|
-
if (verbose)
|
|
810
|
-
logerror("2nd stage: write on-chip memory\n");
|
|
811
|
-
status = parse_ihex(image, &ctx, is_external, ram_poke);
|
|
812
|
-
if (status < 0) {
|
|
813
|
-
logerror("unable to completely upload %s\n", path);
|
|
814
|
-
ret = status;
|
|
815
|
-
goto exit;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
if (verbose && (ctx.count != 0)) {
|
|
820
|
-
logerror("... WROTE: %d bytes, %d segments, avg %d\n",
|
|
821
|
-
(int)ctx.total, (int)ctx.count, (int)(ctx.total/ctx.count));
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
/* if required, reset the CPU so it runs what we just uploaded */
|
|
825
|
-
if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, true))
|
|
826
|
-
ret = -1;
|
|
827
|
-
|
|
828
|
-
exit:
|
|
829
|
-
fclose(image);
|
|
830
|
-
return ret;
|
|
831
|
-
}
|