diff options
author | Cástor Muñoz <cmvidal@gmail.com> | 2017-05-04 10:52:03 +0200 |
---|---|---|
committer | Cástor Muñoz <cmvidal@gmail.com> | 2017-06-19 02:00:30 +0200 |
commit | fbbba9292b07d91916d330b31e7f8644d65ff91a (patch) | |
tree | 191d6ad03986d3e469a1dc32c11f2d423601dec7 /rbutil/mks5lboot | |
parent | cf168d4636b81e414f11ef2c69b1430302d33c3b (diff) | |
download | rockbox-fbbba9292b07d91916d330b31e7f8644d65ff91a.tar.gz rockbox-fbbba9292b07d91916d330b31e7f8644d65ff91a.zip |
mks5lboot: updates
- fix Makefile to allow cross compilation
- Windows: use Sleep() instead of nanosleep()
- Windows: libusb now is optional
- OS X: use IOKit instead of libusb
- small rework on the DFU API
Change-Id: Ia4b07012c098ad608594e15f6effe9c9d2164b9b
Diffstat (limited to 'rbutil/mks5lboot')
-rw-r--r-- | rbutil/mks5lboot/.gitignore | 3 | ||||
-rw-r--r-- | rbutil/mks5lboot/Makefile | 20 | ||||
-rw-r--r-- | rbutil/mks5lboot/README | 49 | ||||
-rw-r--r-- | rbutil/mks5lboot/ipoddfu.c | 624 | ||||
-rw-r--r-- | rbutil/mks5lboot/main.c | 41 | ||||
-rw-r--r-- | rbutil/mks5lboot/mkdfu.c | 22 |
6 files changed, 492 insertions, 267 deletions
diff --git a/rbutil/mks5lboot/.gitignore b/rbutil/mks5lboot/.gitignore index 9078451a7a..9b9b1de6ab 100644 --- a/rbutil/mks5lboot/.gitignore +++ b/rbutil/mks5lboot/.gitignore | |||
@@ -1,2 +1,5 @@ | |||
1 | buildposix/ | 1 | buildposix/ |
2 | buildmingw/ | ||
3 | builddarwin/ | ||
2 | mks5lboot | 4 | mks5lboot |
5 | mks5lboot.exe | ||
diff --git a/rbutil/mks5lboot/Makefile b/rbutil/mks5lboot/Makefile index ba118eefd0..72ea521d5f 100644 --- a/rbutil/mks5lboot/Makefile +++ b/rbutil/mks5lboot/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | 4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | 5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
6 | # \/ \/ \/ \/ \/ | 6 | # \/ \/ \/ \/ \/ |
7 | CC := gcc | ||
7 | CFLAGS += -Wall -Wextra | 8 | CFLAGS += -Wall -Wextra |
8 | 9 | ||
9 | OUTPUT = mks5lboot | 10 | OUTPUT = mks5lboot |
@@ -15,18 +16,25 @@ SOURCES := $(LIBSOURCES) main.c | |||
15 | # dependencies for binary | 16 | # dependencies for binary |
16 | EXTRADEPS := | 17 | EXTRADEPS := |
17 | 18 | ||
18 | ifeq ($(findstring MINGW,$(shell uname)),MINGW) | 19 | CPPDEFINES := $(shell echo foo | $(CROSS)$(CC) -dM -E -) |
20 | |||
21 | ifeq ($(findstring WIN32,$(CPPDEFINES)),WIN32) | ||
19 | LDOPTS += -lsetupapi | 22 | LDOPTS += -lsetupapi |
20 | # optional libusb support on Windows | 23 | # optional libusb support (needed for WinUSB and libusbK drivers) |
21 | ifdef DISABLE_LIBUSBAPI | 24 | ifeq ($(findstring MINGW,$(CPPDEFINES)),MINGW) |
22 | CFLAGS += -DNO_LIBUSBAPI | 25 | ifeq ($(USE_LIBUSBAPI),1) |
23 | else | 26 | CFLAGS += -DUSE_LIBUSBAPI |
24 | LDOPTS += -Wl,-Bstatic -lusb-1.0 | 27 | LDOPTS += -Wl,-Bstatic -lusb-1.0 |
25 | endif | 28 | endif |
29 | endif | ||
26 | else | 30 | else |
27 | # Linux, OS X | 31 | ifeq ($(findstring APPLE,$(CPPDEFINES)),APPLE) |
32 | LDOPTS += -L/usr/local/lib -framework IOKit -framework CoreFoundation | ||
33 | else # Linux | ||
34 | CFLAGS += -DUSE_LIBUSBAPI | ||
28 | LDOPTS += -lusb-1.0 | 35 | LDOPTS += -lusb-1.0 |
29 | endif | 36 | endif |
37 | endif | ||
30 | 38 | ||
31 | include ../libtools.make | 39 | include ../libtools.make |
32 | 40 | ||
diff --git a/rbutil/mks5lboot/README b/rbutil/mks5lboot/README index c2df299867..c424f7e617 100644 --- a/rbutil/mks5lboot/README +++ b/rbutil/mks5lboot/README | |||
@@ -5,7 +5,7 @@ A tool to install/uninstall a dual bootloader into a s5l8702 based | |||
5 | device: | 5 | device: |
6 | 6 | ||
7 | - iPod Classic 6G | 7 | - iPod Classic 6G |
8 | - iPod Nano 3G (TODO) | 8 | - iPod Nano 3G (WIP) |
9 | 9 | ||
10 | 10 | ||
11 | Usage | 11 | Usage |
@@ -97,32 +97,40 @@ Prerequisites: | |||
97 | [INFO] DFU device state: 2 | 97 | [INFO] DFU device state: 2 |
98 | . When the device is found but there is no driver installed: | 98 | . When the device is found but there is no driver installed: |
99 | [ERR] Could not open USB device: LIBUSB_ERROR_NOT_SUPPORTED | 99 | [ERR] Could not open USB device: LIBUSB_ERROR_NOT_SUPPORTED |
100 | . Then the device is found but driver is not valid (probably a | 100 | . When the device is found but driver is not valid (probably a |
101 | libusb-win32 driver is installed): | 101 | libusb-win32 driver is installed): |
102 | [ERR] Could not set USB configuration: LIBUSB_ERROR_NOT_FOUND | 102 | [ERR] Could not set USB configuration: LIBUSB_ERROR_NOT_FOUND |
103 | . If there is no valid DFU driver installed, try one of these: | 103 | . If there is no valid DFU driver installed, try one of these: |
104 | a) Use Zadig (http://zadig.akeo.ie/) to build and install a WinUSB | 104 | a) Use Zadig (http://zadig.akeo.ie/) to build and install a WinUSB |
105 | (libusb.info) or libusbK driver for your device. Note that | 105 | (libusb.info) or libusbK driver for your device. Note that |
106 | libusb-win32 (libusb0) drivers are not valid for mks5lboot. | 106 | libusb-win32 (libusb0) drivers are not valid for mks5lboot. |
107 | b) Use Apple Mobile Device USB driver (included with iTunes). | 107 | b) Use Apple Mobile Device USB driver (included with iTunes). To |
108 | install this driver without iTunes see https://www.freemyipod.org | ||
109 | /wiki/EmCORE_Installation/iPodClassic/InstalliTunesDrivers | ||
108 | 110 | ||
109 | Command line install: | 111 | Command line install: |
110 | 112 | ||
111 | - If you are using iTunes on Windows, close iTunes and kill (or pause) | 113 | - If you are using iTunes on Windows, close iTunes and kill (or pause) |
112 | iTunesHelper.exe before entering DFU mode. | 114 | iTunesHelper.exe before entering DFU mode. |
113 | 115 | ||
116 | - If you are using iTunes on Mac, quit iTunes and kill (or pause) the | ||
117 | iTunesHelper process before entering DFU mode. | ||
118 | You can use "ps x | grep iTunesHelper" to locate the process <PID>, | ||
119 | use "kill -STOP <PID>" to suspend the process and "kill -CONT <PID>" | ||
120 | to resume it once the bootloader is installed. | ||
121 | |||
114 | - Put you device on DFU mode by pressing and holding SELECT+MENU buttons | 122 | - Put you device on DFU mode by pressing and holding SELECT+MENU buttons |
115 | for about 12 seconds. | 123 | for about 12 seconds. |
116 | 124 | ||
117 | You can notice when the device enters DFU mode running the next command | 125 | You can notice when the device enters DFU mode running the next command |
118 | to scan the USB bus every second (press Ctrl-C to abort the scan): | 126 | to scan the USB bus every second (press Ctrl-C to abort the scan): |
119 | mks5lboot --dfuscan --loop | 127 | ./mks5lboot --dfuscan --loop |
120 | 128 | ||
121 | - To install or update a bootloader, build the DFU installer and send it | 129 | - To install or update a bootloader, build the DFU installer and send it |
122 | to the device: | 130 | to the device: |
123 | mks5lboot --bl-inst /path/to/bootloader-ipod6g.ipod | 131 | ./mks5lboot --bl-inst path/to/bootloader-ipod6g.ipod |
124 | 132 | ||
125 | When the DFU imagen is loaded and executed, the device emits an 'alive' | 133 | When the DFU image is loaded and executed, the device emits an 'alive' |
126 | tone (2000Hz/100ms). When the bootloader is successfully installed then | 134 | tone (2000Hz/100ms). When the bootloader is successfully installed then |
127 | a dual tone beep sounds (1000Hz/100ms+2000Hz/150ms) and the device | 135 | a dual tone beep sounds (1000Hz/100ms+2000Hz/150ms) and the device |
128 | reboots. If something went bad then 330Hz/500ms tone is emited and the | 136 | reboots. If something went bad then 330Hz/500ms tone is emited and the |
@@ -132,10 +140,15 @@ Command line install: | |||
132 | 140 | ||
133 | - To remove a previously installed bootloader, build the DFU uninstaler | 141 | - To remove a previously installed bootloader, build the DFU uninstaler |
134 | and send it to the device: | 142 | and send it to the device: |
135 | mks5lboot --bl-uninst ipod6g | 143 | ./mks5lboot --bl-uninst ipod6g |
144 | |||
145 | Notes: | ||
146 | |||
147 | - If USB access is denied, try to run the mks5lboot tool using a privileged | ||
148 | user (i.e. Administrator or root). | ||
149 | |||
150 | - On Windows, use 'mks5lboot' or 'mks5lboot.exe' instead of './mks5lboot'. | ||
136 | 151 | ||
137 | If USB access is denied, try to run the mks5lboot tool using a privileged | ||
138 | user (i.e. Administrator or root). | ||
139 | 152 | ||
140 | 153 | ||
141 | Dual-Boot | 154 | Dual-Boot |
@@ -192,14 +205,20 @@ To build the DFU single-boot installer and send it to the device: | |||
192 | mks5lboot --bl-inst --single /path/to/bootloader-ipod6g.ipod | 205 | mks5lboot --bl-inst --single /path/to/bootloader-ipod6g.ipod |
193 | 206 | ||
194 | 207 | ||
195 | Compilation | 208 | Build |
196 | ----------- | 209 | ----- |
210 | |||
211 | To build type 'make'. | ||
212 | |||
213 | Linux needs libusb >= 1.0, use your package manager to install libusb. | ||
197 | 214 | ||
198 | Needs libusb > 1.0 installed, tested on: | 215 | For Windows, to build with libusb support type 'make USE_LIBUSBAPI=1'. |
199 | 216 | ||
200 | Linux: gcc-4.9.2 + libusb-1.0.19 | 217 | Tested on: |
201 | Windows XP: mingw32-gcc-4.8.1 + libusbx-1.0.15 | 218 | Linux: gcc-4.9.2 + libusb-1.0.19 |
202 | OS X 10.11: clang-7.3.0 + libusb-1.0.20 | 219 | Windows XP: mingw32-gcc-4.8.1 + libusbx-1.0.15 |
220 | OS X 10.11: clang-7.3.0 + libusb-1.0.20 | ||
221 | MXE: i686-w64-mingw32.static-gcc 5.4.0 + libusb-1.0.21 | ||
203 | 222 | ||
204 | 223 | ||
205 | Hacking | 224 | Hacking |
diff --git a/rbutil/mks5lboot/ipoddfu.c b/rbutil/mks5lboot/ipoddfu.c index 6d303d6603..5e2914af4b 100644 --- a/rbutil/mks5lboot/ipoddfu.c +++ b/rbutil/mks5lboot/ipoddfu.c | |||
@@ -22,28 +22,32 @@ | |||
22 | * KIND, either express or implied. | 22 | * KIND, either express or implied. |
23 | * | 23 | * |
24 | ****************************************************************************/ | 24 | ****************************************************************************/ |
25 | #ifndef NO_LIBUSBAPI | ||
26 | #define USE_LIBUSBAPI | ||
27 | #endif | ||
28 | 25 | ||
29 | #include <stdio.h> | 26 | #include <stdio.h> |
30 | #include <stdlib.h> | 27 | #include <stdlib.h> |
31 | #include <unistd.h> | 28 | #include <unistd.h> |
29 | #include <stdbool.h> | ||
32 | #include <string.h> | 30 | #include <string.h> |
33 | #include <time.h> | ||
34 | #ifdef WIN32 | 31 | #ifdef WIN32 |
35 | #include <windows.h> | 32 | #include <windows.h> |
36 | #include <setupapi.h> | 33 | #include <setupapi.h> |
37 | #include <stdbool.h> | ||
38 | #endif | 34 | #endif |
39 | |||
40 | #ifdef USE_LIBUSBAPI | 35 | #ifdef USE_LIBUSBAPI |
41 | #include <libusb-1.0/libusb.h> | 36 | #include <libusb-1.0/libusb.h> |
42 | #endif | 37 | #endif |
38 | #ifdef __APPLE__ | ||
39 | #include <CoreFoundation/CoreFoundation.h> | ||
40 | #include <IOKit/IOCFPlugIn.h> | ||
41 | #include <IOKit/usb/IOUSBLib.h> | ||
42 | #endif | ||
43 | 43 | ||
44 | #include "mks5lboot.h" | 44 | #include "mks5lboot.h" |
45 | 45 | ||
46 | 46 | ||
47 | #ifdef WIN32 | ||
48 | #define sleep_ms(ms) Sleep(ms) | ||
49 | #else | ||
50 | #include <time.h> | ||
47 | static void sleep_ms(unsigned int ms) | 51 | static void sleep_ms(unsigned int ms) |
48 | { | 52 | { |
49 | struct timespec req; | 53 | struct timespec req; |
@@ -51,36 +55,36 @@ static void sleep_ms(unsigned int ms) | |||
51 | req.tv_nsec = (ms % 1000) * 1000000; | 55 | req.tv_nsec = (ms % 1000) * 1000000; |
52 | nanosleep(&req, NULL); | 56 | nanosleep(&req, NULL); |
53 | } | 57 | } |
58 | #endif | ||
59 | |||
60 | static void put_uint32le(unsigned char* p, uint32_t x) | ||
61 | { | ||
62 | p[0] = x & 0xff; | ||
63 | p[1] = (x >> 8) & 0xff; | ||
64 | p[2] = (x >> 16) & 0xff; | ||
65 | p[3] = (x >> 24) & 0xff; | ||
66 | } | ||
54 | 67 | ||
55 | /* | 68 | /* |
56 | * CRC32 functions | 69 | * CRC32 functions |
57 | * Based on public domain implementation by Finn Yannick Jacobs. | 70 | * Based on public domain implementation by Finn Yannick Jacobs. |
58 | */ | 71 | * |
59 | 72 | * Written and copyright 1999 by Finn Yannick Jacobs | |
60 | /* Written and copyright 1999 by Finn Yannick Jacobs | ||
61 | * No rights were reserved to this, so feel free to | 73 | * No rights were reserved to this, so feel free to |
62 | * manipulate or do with it, what you want or desire :) | 74 | * manipulate or do with it, what you want or desire :) |
63 | */ | 75 | */ |
64 | 76 | ||
65 | #define CRC32_DEFAULT_SEED 0xffffffff | ||
66 | |||
67 | /* crc32table[] built by crc32_init() */ | 77 | /* crc32table[] built by crc32_init() */ |
68 | static unsigned long crc32table[256]; | 78 | static uint32_t crc32table[256]; |
69 | 79 | ||
70 | /* Calculate crc32. Little endian. | 80 | /* Calculate crc32 */ |
71 | * Standard seed is 0xffffffff or 0. | 81 | static uint32_t crc32(void *data, unsigned int len, uint32_t previousCrc32) |
72 | * Some implementations xor result with 0xffffffff after calculation. | ||
73 | */ | ||
74 | static uint32_t crc32(void *data, unsigned int len, uint32_t seed) | ||
75 | { | 82 | { |
76 | uint8_t *d = data; | 83 | uint32_t crc = ~previousCrc32; |
77 | 84 | unsigned char *d = (unsigned char*) data; | |
78 | while (len--) | 85 | while (len--) |
79 | { | 86 | crc = (crc >> 8) ^ crc32table[(crc & 0xFF) ^ *d++]; |
80 | seed = ((seed >> 8) & 0x00FFFFFF) ^ crc32table [(seed ^ *d++) & 0xFF]; | 87 | return ~crc; |
81 | } | ||
82 | |||
83 | return seed; | ||
84 | } | 88 | } |
85 | 89 | ||
86 | /* Calculate crc32table */ | 90 | /* Calculate crc32table */ |
@@ -89,55 +93,49 @@ static void crc32_init() | |||
89 | uint32_t poly = 0xEDB88320L; | 93 | uint32_t poly = 0xEDB88320L; |
90 | uint32_t crc; | 94 | uint32_t crc; |
91 | int i, j; | 95 | int i, j; |
92 | |||
93 | for (i = 0; i < 256; ++i) | 96 | for (i = 0; i < 256; ++i) |
94 | { | 97 | { |
95 | crc = i; | 98 | crc = i; |
96 | 99 | for (j = 0; j < 8; ++j) | |
97 | for (j = 8; j > 0; --j) | ||
98 | { | ||
99 | crc = (crc >> 1) ^ ((crc & 1) ? poly : 0); | 100 | crc = (crc >> 1) ^ ((crc & 1) ? poly : 0); |
100 | } | ||
101 | |||
102 | crc32table[i] = crc; | 101 | crc32table[i] = crc; |
103 | } | 102 | } |
104 | } | 103 | } |
105 | 104 | ||
106 | 105 | /* USB */ | |
107 | /* | ||
108 | * DFU | ||
109 | */ | ||
110 | |||
111 | /* must be pow2 <= wTransferSize (2048) */ | ||
112 | #define DFU_PKT_SZ 2048 | ||
113 | |||
114 | #define APPLE_VID 0x05AC | 106 | #define APPLE_VID 0x05AC |
115 | 107 | ||
116 | static int KNOWN_PIDS[] = | 108 | struct pid_info { |
109 | int pid; | ||
110 | int mode; /* 0->DFU, 1->WTF */ | ||
111 | char *desc; | ||
112 | }; | ||
113 | |||
114 | struct pid_info known_pids[] = | ||
117 | { | 115 | { |
118 | /* DFU */ | 116 | /* DFU */ |
119 | 0x1220, /* Nano 2G */ | 117 | { 0x1220, 0, "Nano 2G" }, |
120 | 0x1223, /* Nano 3G and Classic 1G/2G/3G/4G */ | 118 | { 0x1223, 0, "Nano 3G / Classic" }, |
121 | 0x1224, /* Shuffle 3G */ | 119 | { 0x1224, 0, "Shuffle 3G" }, |
122 | 0x1225, /* Nano 4G */ | 120 | { 0x1225, 0, "Nano 4G" }, |
123 | 0x1231, /* Nano 5G */ | 121 | { 0x1231, 0, "Nano 5G" }, |
124 | 0x1232, /* Nano 6G */ | 122 | { 0x1232, 0, "Nano 6G" }, |
125 | 0x1233, /* Shuffle 4G */ | 123 | { 0x1233, 0, "Shuffle 4G" }, |
126 | 0x1234, /* Nano 7G */ | 124 | { 0x1234, 0, "Nano 7G" }, |
127 | /* WTF */ | 125 | /* WTF */ |
128 | 0x1240, /* Nano 2G */ | 126 | { 0x1240, 1, "Nano 2G" }, |
129 | 0x1241, /* Classic 1G */ | 127 | { 0x1241, 1, "Classic 1G" }, |
130 | 0x1242, /* Nano 3G */ | 128 | { 0x1242, 1, "Nano 3G" }, |
131 | 0x1243, /* Nano 4G */ | 129 | { 0x1243, 1, "Nano 4G" }, |
132 | 0x1245, /* Classic 2G */ | 130 | { 0x1245, 1, "Classic 2G" }, |
133 | 0x1246, /* Nano 5G */ | 131 | { 0x1246, 1, "Nano 5G" }, |
134 | 0x1247, /* Classic 3G */ | 132 | { 0x1247, 1, "Classic 3G" }, |
135 | 0x1248, /* Nano 6G */ | 133 | { 0x1248, 1, "Nano 6G" }, |
136 | 0x1249, /* Nano 7G */ | 134 | { 0x1249, 1, "Nano 7G" }, |
137 | 0x124a, /* Nano 7G */ | 135 | { 0x124a, 1, "Nano 7G" }, |
138 | 0x1250, /* Classic 4G */ | 136 | { 0x1250, 1, "Classic 4G" }, |
139 | 0 | ||
140 | }; | 137 | }; |
138 | #define N_KNOWN_PIDS (sizeof(known_pids)/sizeof(struct pid_info)) | ||
141 | 139 | ||
142 | struct usbControlSetup { | 140 | struct usbControlSetup { |
143 | uint8_t bmRequestType; | 141 | uint8_t bmRequestType; |
@@ -157,8 +155,14 @@ struct usbStatusData { | |||
157 | uint8_t iString; | 155 | uint8_t iString; |
158 | } __attribute__ ((packed)); | 156 | } __attribute__ ((packed)); |
159 | 157 | ||
158 | |||
159 | /* | ||
160 | * DFU API | ||
161 | */ | ||
162 | #define DFU_PKT_SZ 2048 /* must be pow2 <= wTransferSize (2048) */ | ||
163 | |||
160 | /* DFU 1.1 specs */ | 164 | /* DFU 1.1 specs */ |
161 | typedef enum DFUState { | 165 | typedef enum { |
162 | appIDLE = 0, | 166 | appIDLE = 0, |
163 | appDETACH = 1, | 167 | appDETACH = 1, |
164 | dfuIDLE = 2, | 168 | dfuIDLE = 2, |
@@ -172,7 +176,7 @@ typedef enum DFUState { | |||
172 | dfuERROR = 10 | 176 | dfuERROR = 10 |
173 | } DFUState; | 177 | } DFUState; |
174 | 178 | ||
175 | typedef enum DFUStatus { | 179 | typedef enum { |
176 | errNONE = 0, | 180 | errNONE = 0, |
177 | errTARGET = 1, | 181 | errTARGET = 1, |
178 | errFILE = 2, | 182 | errFILE = 2, |
@@ -191,7 +195,7 @@ typedef enum DFUStatus { | |||
191 | errSTALLEDPKT = 15 | 195 | errSTALLEDPKT = 15 |
192 | } DFUStatus; | 196 | } DFUStatus; |
193 | 197 | ||
194 | typedef enum DFURequest { | 198 | typedef enum { |
195 | DFU_DETACH = 0, | 199 | DFU_DETACH = 0, |
196 | DFU_DNLOAD = 1, | 200 | DFU_DNLOAD = 1, |
197 | DFU_UPLOAD = 2, | 201 | DFU_UPLOAD = 2, |
@@ -201,12 +205,17 @@ typedef enum DFURequest { | |||
201 | DFU_ABORT = 6 | 205 | DFU_ABORT = 6 |
202 | } DFURequest; | 206 | } DFURequest; |
203 | 207 | ||
208 | typedef enum { | ||
209 | DFUAPIFail = 0, | ||
210 | DFUAPISuccess, | ||
211 | } dfuAPIResult; | ||
212 | |||
204 | struct dfuDev { | 213 | struct dfuDev { |
205 | struct dfuAPI *api; | 214 | struct dfuAPI *api; |
206 | int found_pid; | 215 | int found_pid; |
207 | int detached; | 216 | int detached; |
208 | char descr[256]; | 217 | char descr[256]; |
209 | int res; /* API result: 1->ok, 0->failure */ | 218 | dfuAPIResult res; |
210 | char err[256]; | 219 | char err[256]; |
211 | /* API private */ | 220 | /* API private */ |
212 | #ifdef WIN32 | 221 | #ifdef WIN32 |
@@ -219,21 +228,25 @@ struct dfuDev { | |||
219 | libusb_device_handle* devh; | 228 | libusb_device_handle* devh; |
220 | int rc; /* libusb return code */ | 229 | int rc; /* libusb return code */ |
221 | #endif | 230 | #endif |
231 | #ifdef __APPLE__ | ||
232 | IOUSBDeviceInterface** dev; | ||
233 | kern_return_t kr; | ||
234 | #endif | ||
222 | }; | 235 | }; |
223 | 236 | ||
224 | struct dfuAPI { | 237 | struct dfuAPI { |
225 | char *name; | 238 | char *name; |
226 | int (*open_fn)(struct dfuDev*, int*); | 239 | dfuAPIResult (*open_fn)(struct dfuDev*, int*); |
227 | int (*dfureq_fn)(struct dfuDev*, struct usbControlSetup*, void*); | 240 | dfuAPIResult (*dfureq_fn)(struct dfuDev*, struct usbControlSetup*, void*); |
228 | int (*reset_fn)(struct dfuDev*); | 241 | dfuAPIResult (*reset_fn)(struct dfuDev*); |
229 | void (*close_fn)(struct dfuDev*); | 242 | void (*close_fn)(struct dfuDev*); |
230 | }; | 243 | }; |
231 | 244 | ||
232 | 245 | ||
233 | /* | 246 | /* |
234 | * low-level (API specific) functions | 247 | * DFU API low-level (specific) functions |
235 | */ | 248 | */ |
236 | static int dfu_check_id(int vid, int pid, int *pid_list) | 249 | static bool dfu_check_id(int vid, int pid, int *pid_list) |
237 | { | 250 | { |
238 | int *p; | 251 | int *p; |
239 | if (vid != APPLE_VID) | 252 | if (vid != APPLE_VID) |
@@ -253,17 +266,17 @@ static void dfu_add_reqerrstr(struct dfuDev *dfuh, struct usbControlSetup *cs) | |||
253 | } | 266 | } |
254 | 267 | ||
255 | #ifdef WIN32 | 268 | #ifdef WIN32 |
256 | static int dfu_winapi_chkrc(struct dfuDev *dfuh, char *str, bool success) | 269 | static bool dfu_winapi_chkrc(struct dfuDev *dfuh, char *str, bool success) |
257 | { | 270 | { |
258 | dfuh->res = (int)success; | 271 | dfuh->res = (success) ? DFUAPISuccess : DFUAPIFail; |
259 | if (!success) { | 272 | if (!success) { |
260 | dfuh->ec = GetLastError(); | 273 | dfuh->ec = GetLastError(); |
261 | snprintf(dfuh->err, sizeof(dfuh->err), "%s error %ld", str, dfuh->ec); | 274 | snprintf(dfuh->err, sizeof(dfuh->err), "%s error %ld", str, dfuh->ec); |
262 | } | 275 | } |
263 | return dfuh->res; | 276 | return success; |
264 | } | 277 | } |
265 | 278 | ||
266 | static int dfu_winapi_request(struct dfuDev *dfuh, | 279 | static dfuAPIResult dfu_winapi_request(struct dfuDev *dfuh, |
267 | struct usbControlSetup* cs, void* data) | 280 | struct usbControlSetup* cs, void* data) |
268 | { | 281 | { |
269 | unsigned char buf[USB_CS_SZ + DFU_PKT_SZ]; | 282 | unsigned char buf[USB_CS_SZ + DFU_PKT_SZ]; |
@@ -284,19 +297,20 @@ static int dfu_winapi_request(struct dfuDev *dfuh, | |||
284 | rc = WriteFile(dfuh->ph, buf, USB_CS_SZ + cs->wLength, &rdwr, NULL); | 297 | rc = WriteFile(dfuh->ph, buf, USB_CS_SZ + cs->wLength, &rdwr, NULL); |
285 | dfu_winapi_chkrc(dfuh, "DFU request failed: WriteFile()", rc); | 298 | dfu_winapi_chkrc(dfuh, "DFU request failed: WriteFile()", rc); |
286 | } | 299 | } |
287 | 300 | if (!rc) | |
288 | if (!dfuh->res) | ||
289 | dfu_add_reqerrstr(dfuh, cs); | 301 | dfu_add_reqerrstr(dfuh, cs); |
302 | |||
290 | return dfuh->res; | 303 | return dfuh->res; |
291 | } | 304 | } |
292 | 305 | ||
293 | static int dfu_winapi_reset(struct dfuDev *dfuh) | 306 | static dfuAPIResult dfu_winapi_reset(struct dfuDev *dfuh) |
294 | { | 307 | { |
295 | DWORD bytesReturned; | 308 | DWORD bytesReturned; |
296 | bool rc = DeviceIoControl(dfuh->fh, 0x22000c, | 309 | bool rc = DeviceIoControl(dfuh->fh, |
297 | NULL, 0, NULL, 0, &bytesReturned, NULL); | 310 | 0x22000c, NULL, 0, NULL, 0, &bytesReturned, NULL); |
298 | return dfu_winapi_chkrc(dfuh, | 311 | dfu_winapi_chkrc(dfuh, |
299 | "Could not reset USB device: DeviceIoControl()", rc); | 312 | "Could not reset USB device: DeviceIoControl()", rc); |
313 | return dfuh->res; | ||
300 | } | 314 | } |
301 | 315 | ||
302 | static void dfu_winapi_close(struct dfuDev *dfuh) | 316 | static void dfu_winapi_close(struct dfuDev *dfuh) |
@@ -314,7 +328,7 @@ static void dfu_winapi_close(struct dfuDev *dfuh) | |||
314 | static const GUID GUID_AAPLDFU = | 328 | static const GUID GUID_AAPLDFU = |
315 | { 0xB8085869L, 0xFEB9, 0x404B, {0x8C, 0xB1, 0x1E, 0x5C, 0x14, 0xFA, 0x8C, 0x54}}; | 329 | { 0xB8085869L, 0xFEB9, 0x404B, {0x8C, 0xB1, 0x1E, 0x5C, 0x14, 0xFA, 0x8C, 0x54}}; |
316 | 330 | ||
317 | static int dfu_winapi_open(struct dfuDev *dfuh, int *pid_list) | 331 | static dfuAPIResult dfu_winapi_open(struct dfuDev *dfuh, int *pid_list) |
318 | { | 332 | { |
319 | const GUID *guid = &GUID_AAPLDFU; | 333 | const GUID *guid = &GUID_AAPLDFU; |
320 | HDEVINFO devinfo = NULL; | 334 | HDEVINFO devinfo = NULL; |
@@ -327,7 +341,7 @@ static int dfu_winapi_open(struct dfuDev *dfuh, int *pid_list) | |||
327 | dfuh->fh = | 341 | dfuh->fh = |
328 | dfuh->ph = INVALID_HANDLE_VALUE; | 342 | dfuh->ph = INVALID_HANDLE_VALUE; |
329 | dfuh->found_pid = 0; | 343 | dfuh->found_pid = 0; |
330 | dfuh->res = 1; /* ok */ | 344 | dfuh->res = DFUAPISuccess; |
331 | dfuh->ec = 0; | 345 | dfuh->ec = 0; |
332 | 346 | ||
333 | /* Get DFU path */ | 347 | /* Get DFU path */ |
@@ -398,16 +412,16 @@ error: | |||
398 | #endif /* WIN32 */ | 412 | #endif /* WIN32 */ |
399 | 413 | ||
400 | #ifdef USE_LIBUSBAPI | 414 | #ifdef USE_LIBUSBAPI |
401 | static int dfu_libusb_chkrc(struct dfuDev *dfuh, char *str) | 415 | static bool dfu_libusb_chkrc(struct dfuDev *dfuh, char *str) |
402 | { | 416 | { |
403 | dfuh->res = (dfuh->rc < LIBUSB_SUCCESS) ? 0 : 1; | 417 | dfuh->res = (dfuh->rc < LIBUSB_SUCCESS) ? DFUAPIFail : DFUAPISuccess; |
404 | if (dfuh->res == 0) | 418 | if (dfuh->res == DFUAPIFail) |
405 | snprintf(dfuh->err, sizeof(dfuh->err), | 419 | snprintf(dfuh->err, sizeof(dfuh->err), |
406 | "%s: %s", str, libusb_error_name(dfuh->rc)); | 420 | "%s: %s", str, libusb_error_name(dfuh->rc)); |
407 | return dfuh->res; | 421 | return (dfuh->res == DFUAPISuccess); |
408 | } | 422 | } |
409 | 423 | ||
410 | static int dfu_libusb_request(struct dfuDev *dfuh, | 424 | static dfuAPIResult dfu_libusb_request(struct dfuDev *dfuh, |
411 | struct usbControlSetup *cs, void *data) | 425 | struct usbControlSetup *cs, void *data) |
412 | { | 426 | { |
413 | dfuh->rc = libusb_control_transfer(dfuh->devh, cs->bmRequestType, | 427 | dfuh->rc = libusb_control_transfer(dfuh->devh, cs->bmRequestType, |
@@ -417,10 +431,11 @@ static int dfu_libusb_request(struct dfuDev *dfuh, | |||
417 | return dfuh->res; | 431 | return dfuh->res; |
418 | } | 432 | } |
419 | 433 | ||
420 | static int dfu_libusb_reset(struct dfuDev *dfuh) | 434 | static dfuAPIResult dfu_libusb_reset(struct dfuDev *dfuh) |
421 | { | 435 | { |
422 | dfuh->rc = libusb_reset_device(dfuh->devh); | 436 | dfuh->rc = libusb_reset_device(dfuh->devh); |
423 | return dfu_libusb_chkrc(dfuh, "Could not reset USB device"); | 437 | dfu_libusb_chkrc(dfuh, "Could not reset USB device"); |
438 | return dfuh->res; | ||
424 | } | 439 | } |
425 | 440 | ||
426 | static void dfu_libusb_close(struct dfuDev *dfuh) | 441 | static void dfu_libusb_close(struct dfuDev *dfuh) |
@@ -438,7 +453,7 @@ static void dfu_libusb_close(struct dfuDev *dfuh) | |||
438 | } | 453 | } |
439 | } | 454 | } |
440 | 455 | ||
441 | static int dfu_libusb_open(struct dfuDev *dfuh, int *pid_list) | 456 | static dfuAPIResult dfu_libusb_open(struct dfuDev *dfuh, int *pid_list) |
442 | { | 457 | { |
443 | struct libusb_device_descriptor desc; | 458 | struct libusb_device_descriptor desc; |
444 | libusb_device **devs = NULL, *dev; | 459 | libusb_device **devs = NULL, *dev; |
@@ -447,7 +462,7 @@ static int dfu_libusb_open(struct dfuDev *dfuh, int *pid_list) | |||
447 | dfuh->devh = NULL; | 462 | dfuh->devh = NULL; |
448 | dfuh->found_pid = 0; | 463 | dfuh->found_pid = 0; |
449 | dfuh->detached = 0; | 464 | dfuh->detached = 0; |
450 | dfuh->res = 1; /* ok */ | 465 | dfuh->res = DFUAPISuccess; |
451 | 466 | ||
452 | dfuh->rc = libusb_init(&(dfuh->ctx)); | 467 | dfuh->rc = libusb_init(&(dfuh->ctx)); |
453 | if (!dfu_libusb_chkrc(dfuh, "Could not init USB library")) { | 468 | if (!dfu_libusb_chkrc(dfuh, "Could not init USB library")) { |
@@ -517,10 +532,138 @@ error: | |||
517 | } | 532 | } |
518 | #endif /* USE_LIBUSBAPI */ | 533 | #endif /* USE_LIBUSBAPI */ |
519 | 534 | ||
520 | /* list of suported APIs: | 535 | #ifdef __APPLE__ |
521 | * Windows: winapi and libusb (optional) | 536 | static bool dfu_iokit_chkrc(struct dfuDev *dfuh, char *str) |
522 | * Linux and OSX: libusb | 537 | { |
523 | */ | 538 | dfuh->res = (dfuh->kr == kIOReturnSuccess) ? DFUAPISuccess : DFUAPIFail; |
539 | if (dfuh->res == DFUAPIFail) | ||
540 | snprintf(dfuh->err, sizeof(dfuh->err), | ||
541 | "%s: error %08x", str, dfuh->kr); | ||
542 | return (dfuh->res == DFUAPISuccess); | ||
543 | } | ||
544 | |||
545 | static dfuAPIResult dfu_iokit_request(struct dfuDev *dfuh, | ||
546 | struct usbControlSetup *cs, void *data) | ||
547 | { | ||
548 | IOUSBDevRequest req; | ||
549 | req.bmRequestType = cs->bmRequestType; | ||
550 | req.bRequest = cs->bRequest; | ||
551 | req.wValue = cs->wValue; | ||
552 | req.wIndex = cs->wIndex; | ||
553 | req.wLength = cs->wLength; | ||
554 | req.pData = data; | ||
555 | |||
556 | dfuh->kr = (*(dfuh->dev))->DeviceRequest(dfuh->dev, &req); | ||
557 | if (!dfu_iokit_chkrc(dfuh, "DFU request failed")) | ||
558 | dfu_add_reqerrstr(dfuh, cs); | ||
559 | |||
560 | return dfuh->res; | ||
561 | } | ||
562 | |||
563 | static dfuAPIResult dfu_iokit_reset(struct dfuDev *dfuh) | ||
564 | { | ||
565 | dfuh->kr = (*(dfuh->dev))->ResetDevice(dfuh->dev); | ||
566 | #if 0 | ||
567 | /* On 10.11+ ResetDevice() returns no error but does not perform | ||
568 | * any reset, just a kernel log message. | ||
569 | * USBDeviceReEnumerate() could be used as a workaround. | ||
570 | */ | ||
571 | dfuh->kr = (*(dfuh->dev))->USBDeviceReEnumerate(dfuh->dev, 0); | ||
572 | #endif | ||
573 | dfu_iokit_chkrc(dfuh, "Could not reset USB device"); | ||
574 | return dfuh->res; | ||
575 | } | ||
576 | |||
577 | static void dfu_iokit_close(struct dfuDev *dfuh) | ||
578 | { | ||
579 | if (dfuh->dev) { | ||
580 | (*(dfuh->dev))->USBDeviceClose(dfuh->dev); | ||
581 | (*(dfuh->dev))->Release(dfuh->dev); | ||
582 | dfuh->dev = NULL; | ||
583 | } | ||
584 | } | ||
585 | |||
586 | static dfuAPIResult dfu_iokit_open(struct dfuDev *dfuh, int *pid_list) | ||
587 | { | ||
588 | kern_return_t kr; | ||
589 | CFMutableDictionaryRef usb_matching_dict = 0; | ||
590 | io_object_t usbDevice; | ||
591 | io_iterator_t usb_iterator = IO_OBJECT_NULL; | ||
592 | IOCFPlugInInterface **plugInInterface = NULL; | ||
593 | IOUSBDeviceInterface **dev = NULL; | ||
594 | HRESULT result; | ||
595 | SInt32 score; | ||
596 | UInt16 vendor; | ||
597 | UInt16 product; | ||
598 | UInt16 release; | ||
599 | |||
600 | dfuh->dev = NULL; | ||
601 | dfuh->found_pid = 0; | ||
602 | dfuh->res = DFUAPISuccess; | ||
603 | |||
604 | usb_matching_dict = IOServiceMatching(kIOUSBDeviceClassName); | ||
605 | dfuh->kr = IOServiceGetMatchingServices( | ||
606 | kIOMasterPortDefault, usb_matching_dict, &usb_iterator); | ||
607 | if (!dfu_iokit_chkrc(dfuh, "Could not get matching services")) | ||
608 | goto error; | ||
609 | |||
610 | while ((usbDevice = IOIteratorNext(usb_iterator))) | ||
611 | { | ||
612 | /* Create an intermediate plug-in */ | ||
613 | kr = IOCreatePlugInInterfaceForService(usbDevice, | ||
614 | kIOUSBDeviceUserClientTypeID, | ||
615 | kIOCFPlugInInterfaceID, | ||
616 | &plugInInterface, | ||
617 | &score); | ||
618 | IOObjectRelease(usbDevice); | ||
619 | |||
620 | if ((kIOReturnSuccess != kr) || !plugInInterface) | ||
621 | continue; /* Unable to create a plugin */ | ||
622 | |||
623 | /* Now create the device interface */ | ||
624 | result = (*plugInInterface)->QueryInterface(plugInInterface, | ||
625 | CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), | ||
626 | (LPVOID*)&dev); | ||
627 | (*plugInInterface)->Release(plugInInterface); | ||
628 | |||
629 | if (result || !dev) | ||
630 | continue; /* Couldn't create a device interface */ | ||
631 | |||
632 | kr = (*dev)->GetDeviceVendor(dev, &vendor); | ||
633 | kr = (*dev)->GetDeviceProduct(dev, &product); | ||
634 | kr = (*dev)->GetDeviceReleaseNumber(dev, &release); | ||
635 | |||
636 | if (!dfu_check_id(vendor, product, pid_list)) { | ||
637 | (*dev)->Release(dev); | ||
638 | continue; | ||
639 | } | ||
640 | |||
641 | /* Device found, open it */ | ||
642 | dfuh->kr = (*dev)->USBDeviceOpen(dev); | ||
643 | if (!dfu_iokit_chkrc(dfuh, "Could not open USB device")) { | ||
644 | (*dev)->Release(dev); | ||
645 | goto error; | ||
646 | } | ||
647 | |||
648 | /* ok */ | ||
649 | dfuh->found_pid = product; | ||
650 | dfuh->dev = dev; | ||
651 | snprintf(dfuh->descr, sizeof(dfuh->descr), | ||
652 | "[%04x:%04x] release: %d", vendor, product, release); | ||
653 | break; | ||
654 | } | ||
655 | |||
656 | bye: | ||
657 | if (usb_iterator != IO_OBJECT_NULL) | ||
658 | IOObjectRelease(usb_iterator); | ||
659 | return dfuh->res; | ||
660 | |||
661 | error: | ||
662 | goto bye; | ||
663 | } | ||
664 | #endif /* __APPLE__ */ | ||
665 | |||
666 | /* list of suported APIs */ | ||
524 | static struct dfuAPI api_list[] = | 667 | static struct dfuAPI api_list[] = |
525 | { | 668 | { |
526 | #ifdef WIN32 | 669 | #ifdef WIN32 |
@@ -538,22 +681,22 @@ static struct dfuAPI api_list[] = | |||
538 | dfu_libusb_close }, | 681 | dfu_libusb_close }, |
539 | #endif | 682 | #endif |
540 | #ifdef __APPLE__ | 683 | #ifdef __APPLE__ |
541 | /* TODO: implement API for OS X < 10.6 ??? */ | 684 | { "IOKit", |
685 | dfu_iokit_open, | ||
686 | dfu_iokit_request, | ||
687 | dfu_iokit_reset, | ||
688 | dfu_iokit_close }, | ||
542 | #endif | 689 | #endif |
543 | }; | 690 | }; |
544 | #define DFU_N_APIS (sizeof(api_list)/sizeof(struct dfuAPI)) | 691 | #define N_DFU_APIS (sizeof(api_list)/sizeof(struct dfuAPI)) |
692 | |||
545 | 693 | ||
546 | /* | 694 | /* |
547 | * mid-layer (common) functions | 695 | * DFU API common functions |
548 | */ | 696 | */ |
549 | static void dfu_set_errstr(struct dfuDev *dfuh, char *str) | ||
550 | { | ||
551 | strncpy(dfuh->err, str, sizeof(dfuh->err)); | ||
552 | } | ||
553 | |||
554 | static int DEBUG_DFUREQ = 0; | 697 | static int DEBUG_DFUREQ = 0; |
555 | 698 | ||
556 | static int dfu_request(struct dfuDev *dfuh, | 699 | static dfuAPIResult dfuapi_request(struct dfuDev *dfuh, |
557 | struct usbControlSetup *cs, void *data) | 700 | struct usbControlSetup *cs, void *data) |
558 | { | 701 | { |
559 | if (!DEBUG_DFUREQ) | 702 | if (!DEBUG_DFUREQ) |
@@ -564,16 +707,17 @@ static int dfu_request(struct dfuDev *dfuh, | |||
564 | /* previous state */ | 707 | /* previous state */ |
565 | unsigned char ste = 0; | 708 | unsigned char ste = 0; |
566 | struct usbControlSetup css = { 0xA1, DFU_GETSTATE, 0, 0, sizeof(ste) }; | 709 | struct usbControlSetup css = { 0xA1, DFU_GETSTATE, 0, 0, sizeof(ste) }; |
567 | if (!dfuh->api->dfureq_fn(dfuh, &css, &ste)) { | 710 | if (dfuh->api->dfureq_fn(dfuh, &css, &ste) != DFUAPISuccess) { |
568 | snprintf(dfuh->err + strlen(dfuh->err), sizeof(dfuh->err) - | 711 | snprintf(dfuh->err + strlen(dfuh->err), sizeof(dfuh->err) - |
569 | strlen(dfuh->err), " [DEBUG_DFUREQ ERROR: state=%d]", ste); | 712 | strlen(dfuh->err), " [DEBUG_DFUREQ ERROR: state=%d]", ste); |
570 | return 0; | 713 | goto error; |
571 | } | 714 | } |
572 | 715 | ||
573 | int ret = dfuh->api->dfureq_fn(dfuh, cs, data); | 716 | dfuh->api->dfureq_fn(dfuh, cs, data); |
574 | fprintf(stderr, "[DEBUG]: REQ: ste=%d, cs=%2x/%d/%d/%d/%d -> %s", | 717 | fprintf(stderr, "[DEBUG]: REQ: ste=%d, cs=%2x/%d/%d/%d/%d -> %s", |
575 | ste, cs->bmRequestType, cs->bRequest, cs->wValue, | 718 | ste, cs->bmRequestType, cs->bRequest, cs->wValue, |
576 | cs->wIndex, cs->wLength, ret ? "ok" : "ERROR"); | 719 | cs->wIndex, cs->wLength, |
720 | (dfuh->res == DFUAPISuccess) ? "ok" : "ERROR"); | ||
577 | if (cs->bRequest == DFU_GETSTATE) | 721 | if (cs->bRequest == DFU_GETSTATE) |
578 | fprintf(stderr, " (state=%d)", *((unsigned char*)(data))); | 722 | fprintf(stderr, " (state=%d)", *((unsigned char*)(data))); |
579 | if (cs->bRequest == DFU_GETSTATUS) { | 723 | if (cs->bRequest == DFU_GETSTATUS) { |
@@ -584,106 +728,189 @@ static int dfu_request(struct dfuDev *dfuh, | |||
584 | } | 728 | } |
585 | fputc('\n', stderr); | 729 | fputc('\n', stderr); |
586 | fflush(stderr); | 730 | fflush(stderr); |
587 | return ret; | 731 | |
732 | bye: | ||
733 | return dfuh->res; | ||
734 | error: | ||
735 | goto bye; | ||
588 | } | 736 | } |
589 | 737 | ||
590 | static int dfureq_getstatus(struct dfuDev *dfuh, int *status, | 738 | static dfuAPIResult dfuapi_req_getstatus(struct dfuDev *dfuh, |
591 | int *poll_tmo /*ms*/, int *state) | 739 | DFUStatus *status, int *poll_tmo /*ms*/, |
740 | DFUState *state) | ||
592 | { | 741 | { |
593 | struct usbStatusData sd = { 0, 0, 0, 0, 0, 0 }; | 742 | struct usbStatusData sd = { 0, 0, 0, 0, 0, 0 }; |
594 | struct usbControlSetup cs = { 0xA1, DFU_GETSTATUS, 0, 0, sizeof(sd) }; | 743 | struct usbControlSetup cs = { 0xA1, DFU_GETSTATUS, 0, 0, sizeof(sd) }; |
595 | int ret = dfu_request(dfuh, &cs, &sd); | 744 | dfuapi_request(dfuh, &cs, &sd); |
596 | if (status) *status = sd.bStatus; | 745 | if (status) *status = sd.bStatus; |
597 | if (state) *state = sd.bState; | 746 | if (state) *state = sd.bState; |
598 | if (poll_tmo) *poll_tmo = (sd.bwPollTimeout2 << 16) | | 747 | if (poll_tmo) *poll_tmo = (sd.bwPollTimeout2 << 16) | |
599 | (sd.bwPollTimeout1 << 8) | (sd.bwPollTimeout0); | 748 | (sd.bwPollTimeout1 << 8) | (sd.bwPollTimeout0); |
600 | return ret; | 749 | return dfuh->res; |
601 | } | 750 | } |
602 | 751 | ||
603 | static int dfureq_getstate(struct dfuDev *dfuh, int *state) | 752 | static dfuAPIResult dfuapi_req_getstate(struct dfuDev *dfuh, DFUState *state) |
604 | { | 753 | { |
605 | if (!state) | ||
606 | return 1; /* nothing to do */ | ||
607 | unsigned char sts = 0; | 754 | unsigned char sts = 0; |
608 | struct usbControlSetup cs = { 0xA1, DFU_GETSTATE, 0, 0, sizeof(sts) }; | 755 | struct usbControlSetup cs = { 0xA1, DFU_GETSTATE, 0, 0, sizeof(sts) }; |
609 | int ret = dfu_request(dfuh, &cs, &sts); | 756 | dfuapi_request(dfuh, &cs, &sts); |
610 | *state = sts; | 757 | if (state) *state = sts; |
611 | return ret; | 758 | return dfuh->res; |
612 | } | 759 | } |
613 | 760 | ||
614 | static int dfureq_dnload(struct dfuDev* dfuh, uint16_t blknum, | 761 | static dfuAPIResult dfuapi_req_dnload(struct dfuDev* dfuh, uint16_t blknum, |
615 | uint16_t len, unsigned char *data) | 762 | uint16_t len, unsigned char *data) |
616 | { | 763 | { |
617 | struct usbControlSetup cs = { 0x21, DFU_DNLOAD, blknum, 0, len }; | 764 | struct usbControlSetup cs = { 0x21, DFU_DNLOAD, blknum, 0, len }; |
618 | return dfu_request(dfuh, &cs, data); | 765 | return dfuapi_request(dfuh, &cs, data); |
619 | } | 766 | } |
620 | 767 | ||
621 | /* not used */ | 768 | /* not used */ |
622 | #if 0 | 769 | #if 0 |
623 | static int dfureq_upload(struct dfuDev* dfuh, | 770 | static dfuAPIResult dfuapi_req_upload(struct dfuDev* dfuh, |
624 | uint16_t blknum, uint16_t len, unsigned char *data) | 771 | uint16_t blknum, uint16_t len, unsigned char *data) |
625 | { | 772 | { |
626 | struct usbControlSetup cs = { 0xA1, DFU_UPLOAD, blknum, 0, len }; | 773 | struct usbControlSetup cs = { 0xA1, DFU_UPLOAD, blknum, 0, len }; |
627 | return dfu_request(dfuh, &cs, data); | 774 | return dfuapi_request(dfuh, &cs, data); |
628 | } | 775 | } |
629 | 776 | ||
630 | static int dfureq_clrstatus(struct dfuDev* dfuh) | 777 | static dfuAPIResult dfuapi_req_clrstatus(struct dfuDev* dfuh) |
631 | { | 778 | { |
632 | struct usbControlSetup cs = { 0x21, DFU_CLRSTATUS, 0, 0, 0 }; | 779 | struct usbControlSetup cs = { 0x21, DFU_CLRSTATUS, 0, 0, 0 }; |
633 | return dfu_request(dfuh, &cs, NULL); | 780 | return dfuapi_request(dfuh, &cs, NULL); |
634 | } | 781 | } |
635 | 782 | ||
636 | static int dfureq_abort(struct dfuDev* dfuh) | 783 | static dfuAPIResult dfuapi_req_abort(struct dfuDev* dfuh) |
637 | { | 784 | { |
638 | struct usbControlSetup cs = { 0x21, DFU_ABORT, 0, 0, 0 }; | 785 | struct usbControlSetup cs = { 0x21, DFU_ABORT, 0, 0, 0 }; |
639 | return dfu_request(dfuh, &cs, NULL); | 786 | return dfuapi_request(dfuh, &cs, NULL); |
640 | } | 787 | } |
641 | 788 | ||
642 | /* not implemented on DFU8702 */ | 789 | /* not implemented on DFU8702 */ |
643 | static int dfureq_detach(struct dfuDev* dfuh, int tmo) | 790 | static dfuAPIResult dfuapi_req_detach(struct dfuDev* dfuh, int tmo) |
644 | { | 791 | { |
645 | struct usbControlSetup cs = { 0x21, DFU_DETACH, tmo, 0, 0 }; | 792 | struct usbControlSetup cs = { 0x21, DFU_DETACH, tmo, 0, 0 }; |
646 | return dfu_request(dfuh, &cs, NULL); | 793 | return dfuapi_request(dfuh, &cs, NULL); |
647 | } | 794 | } |
648 | #endif | 795 | #endif |
649 | 796 | ||
650 | static int dfu_send_packet(struct dfuDev* dfuh, uint16_t blknum, | 797 | static dfuAPIResult dfuapi_reset(struct dfuDev *dfuh) |
651 | uint16_t len, unsigned char *data, int *status, | ||
652 | int *poll_tmo, int *state, int *pre_state) | ||
653 | { | 798 | { |
654 | if (!dfureq_dnload(dfuh, blknum, len, data)) | 799 | return dfuh->api->reset_fn(dfuh); |
655 | return 0; | 800 | } |
801 | |||
802 | static dfuAPIResult dfuapi_send_packet(struct dfuDev* dfuh, uint16_t blknum, | ||
803 | uint16_t len, unsigned char *data, DFUStatus *status, | ||
804 | int *poll_tmo, DFUState *state, DFUState *pre_state) | ||
805 | { | ||
806 | if (dfuapi_req_dnload(dfuh, blknum, len, data) != DFUAPISuccess) | ||
807 | goto error; | ||
656 | 808 | ||
657 | /* device is in dfuDLSYNC state, waiting for a GETSTATUS request | 809 | /* device is in dfuDLSYNC state, waiting for a GETSTATUS request |
658 | to enter the next state, if she respond with dfuDLBUSY then | 810 | * to enter the next state, if she respond with dfuDLBUSY then |
659 | we must wait to resend the GETSTATUS request */ | 811 | * we must wait to resend the GETSTATUS request */ |
660 | 812 | ||
661 | if (!dfureq_getstatus(dfuh, status, poll_tmo, state)) | 813 | if (dfuapi_req_getstatus(dfuh, status, poll_tmo, state) != DFUAPISuccess) |
662 | return 0; | 814 | goto error; |
663 | 815 | ||
664 | if (*state == dfuDNBUSY) { | 816 | if (*state == dfuDNBUSY) { |
665 | if (*poll_tmo) | 817 | if (*poll_tmo) |
666 | sleep_ms(*poll_tmo); | 818 | sleep_ms(*poll_tmo); |
667 | if (!dfureq_getstate(dfuh, pre_state)) | 819 | if (pre_state) |
668 | return 0; | 820 | if (dfuapi_req_getstate(dfuh, pre_state) != DFUAPISuccess) |
669 | if (!dfureq_getstatus(dfuh, status, poll_tmo, state)) | 821 | goto error; |
670 | return 0; | 822 | if (dfuapi_req_getstatus(dfuh, status, poll_tmo, state) != DFUAPISuccess) |
823 | goto error; | ||
671 | } | 824 | } |
672 | 825 | ||
673 | return 1; | 826 | bye: |
827 | return dfuh->res; | ||
828 | error: | ||
829 | goto bye; | ||
830 | } | ||
831 | |||
832 | static void dfuapi_set_err(struct dfuDev *dfuh, char *str) | ||
833 | { | ||
834 | dfuh->res = DFUAPIFail; | ||
835 | strncpy(dfuh->err, str, sizeof(dfuh->err)); | ||
836 | } | ||
837 | |||
838 | static dfuAPIResult dfuapi_open(struct dfuDev *dfuh, int pid) | ||
839 | { | ||
840 | int pid_l[N_KNOWN_PIDS+1] = { 0 }; | ||
841 | struct dfuAPI *api; | ||
842 | unsigned i, p; | ||
843 | |||
844 | /* fill pid list */ | ||
845 | if (pid) | ||
846 | pid_l[0] = pid; | ||
847 | else | ||
848 | for (p = 0; p < N_KNOWN_PIDS; p++) | ||
849 | pid_l[p] = known_pids[p].pid; | ||
850 | |||
851 | for (i = 0; i < N_DFU_APIS; i++) | ||
852 | { | ||
853 | api = &api_list[i]; | ||
854 | if (api->open_fn(dfuh, pid_l) != DFUAPISuccess) | ||
855 | goto error; | ||
856 | if (dfuh->found_pid) { | ||
857 | /* ok */ | ||
858 | dfuh->api = api; | ||
859 | printf("[INFO] %s: found %s\n", api->name, dfuh->descr); | ||
860 | for (p = 0; p < N_KNOWN_PIDS; p++) { | ||
861 | if (known_pids[p].pid == dfuh->found_pid) { | ||
862 | printf("[INFO] iPod %s, mode: %s\n", known_pids[p].desc, | ||
863 | known_pids[p].mode ? "WTF" : "DFU"); | ||
864 | break; | ||
865 | } | ||
866 | } | ||
867 | fflush(stdout); | ||
868 | goto bye; | ||
869 | } | ||
870 | printf("[INFO] %s: no DFU devices found\n", api->name); | ||
871 | fflush(stdout); | ||
872 | } | ||
873 | |||
874 | /* error */ | ||
875 | dfuapi_set_err(dfuh, "DFU device not found"); | ||
876 | |||
877 | bye: | ||
878 | return dfuh->res; | ||
879 | error: | ||
880 | goto bye; | ||
674 | } | 881 | } |
675 | 882 | ||
676 | static int dfu_download_file(struct dfuDev* dfuh, | 883 | static void dfuapi_destroy(struct dfuDev *dfuh) |
884 | { | ||
885 | if (dfuh) { | ||
886 | if (dfuh->api) | ||
887 | dfuh->api->close_fn(dfuh); | ||
888 | free(dfuh); | ||
889 | } | ||
890 | } | ||
891 | |||
892 | static struct dfuDev *dfuapi_create(void) | ||
893 | { | ||
894 | return calloc(sizeof(struct dfuDev), 1); | ||
895 | } | ||
896 | |||
897 | |||
898 | /* | ||
899 | * app level functions | ||
900 | */ | ||
901 | static int ipoddfu_download_file(struct dfuDev* dfuh, | ||
677 | unsigned char *data, unsigned long size) | 902 | unsigned char *data, unsigned long size) |
678 | { | 903 | { |
679 | unsigned int blknum, len, remaining; | 904 | unsigned int blknum, len, remaining; |
680 | int status, poll_tmo, state; | 905 | int poll_tmo; |
906 | DFUStatus status; | ||
907 | DFUState state; | ||
681 | 908 | ||
682 | if (!dfureq_getstate(dfuh, &state)) | 909 | if (dfuapi_req_getstate(dfuh, &state) != DFUAPISuccess) |
683 | goto error; | 910 | goto error; |
684 | 911 | ||
685 | if (state != dfuIDLE) { | 912 | if (state != dfuIDLE) { |
686 | dfu_set_errstr(dfuh, "Could not start DFU download: not idle"); | 913 | dfuapi_set_err(dfuh, "Could not start DFU download: not idle"); |
687 | goto error; | 914 | goto error; |
688 | } | 915 | } |
689 | 916 | ||
@@ -693,12 +920,12 @@ static int dfu_download_file(struct dfuDev* dfuh, | |||
693 | { | 920 | { |
694 | len = (remaining < DFU_PKT_SZ) ? remaining : DFU_PKT_SZ; | 921 | len = (remaining < DFU_PKT_SZ) ? remaining : DFU_PKT_SZ; |
695 | 922 | ||
696 | if (!dfu_send_packet(dfuh, blknum, len, data + | 923 | if (dfuapi_send_packet(dfuh, blknum, len, data + blknum*DFU_PKT_SZ, |
697 | blknum*DFU_PKT_SZ, &status, &poll_tmo, &state, NULL)) | 924 | &status, &poll_tmo, &state, NULL) != DFUAPISuccess) |
698 | goto error; | 925 | goto error; |
699 | 926 | ||
700 | if (state != dfuDNLOAD_IDLE) { | 927 | if (state != dfuDNLOAD_IDLE) { |
701 | dfu_set_errstr(dfuh, "DFU download aborted: unexpected state"); | 928 | dfuapi_set_err(dfuh, "DFU download aborted: unexpected state"); |
702 | goto error; | 929 | goto error; |
703 | } | 930 | } |
704 | 931 | ||
@@ -707,9 +934,9 @@ static int dfu_download_file(struct dfuDev* dfuh, | |||
707 | } | 934 | } |
708 | 935 | ||
709 | /* send ZLP */ | 936 | /* send ZLP */ |
710 | int pre_state = 0; | 937 | DFUState pre_state = appIDLE; /* dummy state */ |
711 | if (!dfu_send_packet(dfuh, blknum, 0, NULL, | 938 | if (dfuapi_send_packet(dfuh, blknum, 0, NULL, |
712 | &status, &poll_tmo, &state, &pre_state)) { | 939 | &status, &poll_tmo, &state, &pre_state) != DFUAPISuccess) { |
713 | if (pre_state == dfuMANIFEST_SYNC) | 940 | if (pre_state == dfuMANIFEST_SYNC) |
714 | goto ok; /* pwnaged .dfu file */ | 941 | goto ok; /* pwnaged .dfu file */ |
715 | goto error; | 942 | goto error; |
@@ -717,9 +944,9 @@ static int dfu_download_file(struct dfuDev* dfuh, | |||
717 | 944 | ||
718 | if (state != dfuMANIFEST) { | 945 | if (state != dfuMANIFEST) { |
719 | if (status == errFIRMWARE) | 946 | if (status == errFIRMWARE) |
720 | dfu_set_errstr(dfuh, "DFU download failed: corrupt firmware"); | 947 | dfuapi_set_err(dfuh, "DFU download failed: corrupt firmware"); |
721 | else | 948 | else |
722 | dfu_set_errstr(dfuh, "DFU download failed: unexpected state"); | 949 | dfuapi_set_err(dfuh, "DFU download failed: unexpected state"); |
723 | goto error; | 950 | goto error; |
724 | } | 951 | } |
725 | 952 | ||
@@ -727,21 +954,20 @@ static int dfu_download_file(struct dfuDev* dfuh, | |||
727 | if (poll_tmo) | 954 | if (poll_tmo) |
728 | sleep_ms(poll_tmo); | 955 | sleep_ms(poll_tmo); |
729 | 956 | ||
730 | if (!dfureq_getstatus(dfuh, &status, NULL, &state)) | 957 | if (dfuapi_req_getstatus(dfuh, &status, NULL, &state) != DFUAPISuccess) |
731 | goto ok; /* 1223 .dfu file */ | 958 | goto ok; /* 1223 .dfu file */ |
732 | 959 | ||
733 | 960 | /* XXX: next code never tested */ | |
734 | /* TODO: next code never tested */ | ||
735 | 961 | ||
736 | if (state != dfuMANIFEST_WAIT_RESET) { | 962 | if (state != dfuMANIFEST_WAIT_RESET) { |
737 | if (status == errVERIFY) | 963 | if (status == errVERIFY) |
738 | dfu_set_errstr(dfuh, "DFU manifest failed: wrong FW verification"); | 964 | dfuapi_set_err(dfuh, "DFU manifest failed: wrong FW verification"); |
739 | else | 965 | else |
740 | dfu_set_errstr(dfuh, "DFU manifest failed: unexpected state"); | 966 | dfuapi_set_err(dfuh, "DFU manifest failed: unexpected state"); |
741 | goto error; | 967 | goto error; |
742 | } | 968 | } |
743 | 969 | ||
744 | if (!dfuh->api->reset_fn(dfuh)) | 970 | if (dfuapi_reset(dfuh) != DFUAPISuccess) |
745 | goto error; | 971 | goto error; |
746 | 972 | ||
747 | ok: | 973 | ok: |
@@ -750,86 +976,42 @@ error: | |||
750 | return 0; | 976 | return 0; |
751 | } | 977 | } |
752 | 978 | ||
753 | static int dfu_open(struct dfuDev *dfuh, int pid) | 979 | /* exported functions */ |
754 | { | ||
755 | int pid_l[2] = {0}; | ||
756 | struct dfuAPI *api; | ||
757 | unsigned i; | ||
758 | |||
759 | pid_l[0] = pid; | ||
760 | |||
761 | for (i = 0; i < DFU_N_APIS; i++) | ||
762 | { | ||
763 | api = &api_list[i]; | ||
764 | if (!(api->open_fn(dfuh, pid ? pid_l : KNOWN_PIDS))) | ||
765 | return 0; /* error */ | ||
766 | if (dfuh->found_pid) { | ||
767 | dfuh->api = api; | ||
768 | printf("[INFO] %s: found %s\n", api->name, dfuh->descr); | ||
769 | fflush(stdout); | ||
770 | return 1; /* ok */ | ||
771 | } | ||
772 | printf("[INFO] %s: no DFU devices found\n", api->name); | ||
773 | fflush(stdout); | ||
774 | } | ||
775 | |||
776 | dfu_set_errstr(dfuh, "DFU device not found"); | ||
777 | return 0; | ||
778 | } | ||
779 | |||
780 | static void dfu_destroy(struct dfuDev *dfuh) | ||
781 | { | ||
782 | if (dfuh) { | ||
783 | if (dfuh->api) | ||
784 | dfuh->api->close_fn(dfuh); | ||
785 | free(dfuh); | ||
786 | } | ||
787 | } | ||
788 | |||
789 | static struct dfuDev *dfu_create() | ||
790 | { | ||
791 | return calloc(sizeof(struct dfuDev), 1); | ||
792 | } | ||
793 | |||
794 | /* | ||
795 | * exported functions | ||
796 | */ | ||
797 | int ipoddfu_send(int pid, unsigned char *data, int size, | 980 | int ipoddfu_send(int pid, unsigned char *data, int size, |
798 | char* errstr, int errstrsize) | 981 | char* errstr, int errstrsize) |
799 | { | 982 | { |
800 | struct dfuDev *dfuh; | 983 | struct dfuDev *dfuh; |
801 | unsigned char *buf; | 984 | unsigned char *buf; |
802 | unsigned int checksum; | 985 | uint32_t checksum; |
803 | int ret = 1; /* ok */ | 986 | int ret = 1; /* ok */ |
804 | 987 | ||
805 | dfuh = dfu_create(); | 988 | dfuh = dfuapi_create(); |
806 | 989 | ||
807 | buf = malloc(size+4); | 990 | buf = malloc(size+4); |
808 | if (!buf) { | 991 | if (!buf) { |
809 | dfu_set_errstr(dfuh, "Could not allocate memory for DFU buffer"); | 992 | dfuapi_set_err(dfuh, "Could not allocate memory for DFU buffer"); |
810 | goto error; | 993 | goto error; |
811 | } | 994 | } |
812 | 995 | ||
813 | if (memcmp(data, IM3_IDENT, 4)) { | 996 | if (memcmp(data, IM3_IDENT, 4)) { |
814 | dfu_set_errstr(dfuh, "Bad DFU image data"); | 997 | dfuapi_set_err(dfuh, "Bad DFU image data"); |
815 | goto error; | 998 | goto error; |
816 | } | 999 | } |
817 | 1000 | ||
818 | /* FIXME: big endian */ | ||
819 | crc32_init(); | 1001 | crc32_init(); |
820 | checksum = crc32(data, size, CRC32_DEFAULT_SEED); | 1002 | checksum = crc32(data, size, 0); |
821 | memcpy(buf, data, size); | 1003 | memcpy(buf, data, size); |
822 | memcpy(buf+size, &checksum, 4); | 1004 | put_uint32le(buf+size, ~checksum); |
823 | 1005 | ||
824 | if (!dfu_open(dfuh, pid)) | 1006 | if (dfuapi_open(dfuh, pid) != DFUAPISuccess) |
825 | goto error; | 1007 | goto error; |
826 | 1008 | ||
827 | if (!dfu_download_file(dfuh, buf, size+4)) | 1009 | if (!ipoddfu_download_file(dfuh, buf, size+4)) |
828 | goto error; | 1010 | goto error; |
829 | 1011 | ||
830 | bye: | 1012 | bye: |
831 | if (buf) free(buf); | 1013 | if (buf) free(buf); |
832 | dfu_destroy(dfuh); | 1014 | dfuapi_destroy(dfuh); |
833 | return ret; | 1015 | return ret; |
834 | 1016 | ||
835 | error: | 1017 | error: |
@@ -846,20 +1028,24 @@ int ipoddfu_scan(int pid, int *state, int reset, | |||
846 | struct dfuDev *dfuh; | 1028 | struct dfuDev *dfuh; |
847 | int ret = 1; /* ok */ | 1029 | int ret = 1; /* ok */ |
848 | 1030 | ||
849 | dfuh = dfu_create(); | 1031 | dfuh = dfuapi_create(); |
850 | 1032 | ||
851 | if (!dfu_open(dfuh, pid)) | 1033 | if (dfuapi_open(dfuh, pid) != DFUAPISuccess) |
852 | goto error; | 1034 | goto error; |
853 | 1035 | ||
854 | if (reset) | 1036 | if (reset) |
855 | if (!dfuh->api->reset_fn(dfuh)) | 1037 | if (dfuapi_reset(dfuh) != DFUAPISuccess) |
856 | goto error; | 1038 | goto error; |
857 | 1039 | ||
858 | if (!dfureq_getstate(dfuh, state)) | 1040 | if (state) { |
859 | goto error; | 1041 | DFUState sts; |
1042 | if (dfuapi_req_getstate(dfuh, &sts) != DFUAPISuccess) | ||
1043 | goto error; | ||
1044 | *state = (int)sts; | ||
1045 | } | ||
860 | 1046 | ||
861 | bye: | 1047 | bye: |
862 | dfu_destroy(dfuh); | 1048 | dfuapi_destroy(dfuh); |
863 | return ret; | 1049 | return ret; |
864 | 1050 | ||
865 | error: | 1051 | error: |
diff --git a/rbutil/mks5lboot/main.c b/rbutil/mks5lboot/main.c index 98c85b9bb7..31e16eca82 100644 --- a/rbutil/mks5lboot/main.c +++ b/rbutil/mks5lboot/main.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <string.h> | 24 | #include <string.h> |
25 | #include <unistd.h> | 25 | #include <unistd.h> |
26 | #include <fcntl.h> | 26 | #include <fcntl.h> |
27 | #include <time.h> | ||
28 | #include <sys/types.h> | 27 | #include <sys/types.h> |
29 | #include <sys/stat.h> | 28 | #include <sys/stat.h> |
30 | 29 | ||
@@ -35,9 +34,23 @@ | |||
35 | #define O_BINARY 0 | 34 | #define O_BINARY 0 |
36 | #endif | 35 | #endif |
37 | 36 | ||
37 | #ifdef WIN32 | ||
38 | #include <windows.h> | ||
39 | #define sleep_ms(ms) Sleep(ms) | ||
40 | #else | ||
41 | #include <time.h> | ||
42 | static void sleep_ms(unsigned int ms) | ||
43 | { | ||
44 | struct timespec req; | ||
45 | req.tv_sec = ms / 1000; | ||
46 | req.tv_nsec = (ms % 1000) * 1000000; | ||
47 | nanosleep(&req, NULL); | ||
48 | } | ||
49 | #endif | ||
50 | |||
38 | #define DEFAULT_LOOP_PERIOD 1 /* seconds */ | 51 | #define DEFAULT_LOOP_PERIOD 1 /* seconds */ |
39 | 52 | ||
40 | #define ERROR(format, ...) \ | 53 | #define _ERR(format, ...) \ |
41 | do { \ | 54 | do { \ |
42 | snprintf(errstr, errstrsize, "[ERR] "format, __VA_ARGS__); \ | 55 | snprintf(errstr, errstrsize, "[ERR] "format, __VA_ARGS__); \ |
43 | goto error; \ | 56 | goto error; \ |
@@ -48,10 +61,10 @@ static int write_file(char *outfile, unsigned char* buf, | |||
48 | { | 61 | { |
49 | int fd = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666); | 62 | int fd = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666); |
50 | if (fd < 0) | 63 | if (fd < 0) |
51 | ERROR("Could not open %s for writing", outfile); | 64 | _ERR("Could not open %s for writing", outfile); |
52 | 65 | ||
53 | if (write(fd, buf, bufsize) != bufsize) | 66 | if (write(fd, buf, bufsize) != bufsize) |
54 | ERROR("Could not write file %s", outfile); | 67 | _ERR("Could not write file %s", outfile); |
55 | 68 | ||
56 | return 1; | 69 | return 1; |
57 | 70 | ||
@@ -68,19 +81,19 @@ static unsigned char *read_file(char *infile, int *bufsize, | |||
68 | 81 | ||
69 | fd = open(infile, O_RDONLY|O_BINARY); | 82 | fd = open(infile, O_RDONLY|O_BINARY); |
70 | if (fd < 0) | 83 | if (fd < 0) |
71 | ERROR("Could not open %s for reading", infile); | 84 | _ERR("Could not open %s for reading", infile); |
72 | 85 | ||
73 | if (fstat(fd, &s) < 0) | 86 | if (fstat(fd, &s) < 0) |
74 | ERROR("Checking size of input file %s", infile); | 87 | _ERR("Checking size of input file %s", infile); |
75 | 88 | ||
76 | *bufsize = s.st_size; | 89 | *bufsize = s.st_size; |
77 | 90 | ||
78 | buf = malloc(*bufsize); | 91 | buf = malloc(*bufsize); |
79 | if (buf == NULL) | 92 | if (buf == NULL) |
80 | ERROR("Could not allocate memory for %s", infile); | 93 | _ERR("Could not allocate memory for %s", infile); |
81 | 94 | ||
82 | if (read(fd, buf, *bufsize) != *bufsize) | 95 | if (read(fd, buf, *bufsize) != *bufsize) |
83 | ERROR("Could not read file %s", infile); | 96 | _ERR("Could not read file %s", infile); |
84 | 97 | ||
85 | return buf; | 98 | return buf; |
86 | 99 | ||
@@ -88,14 +101,6 @@ error: | |||
88 | return NULL; | 101 | return NULL; |
89 | } | 102 | } |
90 | 103 | ||
91 | static void sleep_ms(unsigned int ms) | ||
92 | { | ||
93 | struct timespec req; | ||
94 | req.tv_sec = ms / 1000; | ||
95 | req.tv_nsec = (ms % 1000) * 1000000; | ||
96 | nanosleep(&req, NULL); | ||
97 | } | ||
98 | |||
99 | static void usage(void) | 104 | static void usage(void) |
100 | { | 105 | { |
101 | fprintf(stderr, | 106 | fprintf(stderr, |
@@ -169,7 +174,11 @@ int main(int argc, char* argv[]) | |||
169 | int dfusize; | 174 | int dfusize; |
170 | 175 | ||
171 | fprintf(stderr, | 176 | fprintf(stderr, |
177 | #if defined(WIN32) && defined(USE_LIBUSBAPI) | ||
178 | "mks5lboot Version " VERSION " (libusb)\n" | ||
179 | #else | ||
172 | "mks5lboot Version " VERSION "\n" | 180 | "mks5lboot Version " VERSION "\n" |
181 | #endif | ||
173 | "This is free software; see the source for copying conditions. There is NO\n" | 182 | "This is free software; see the source for copying conditions. There is NO\n" |
174 | "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" | 183 | "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" |
175 | "\n"); | 184 | "\n"); |
diff --git a/rbutil/mks5lboot/mkdfu.c b/rbutil/mks5lboot/mkdfu.c index 6ac0daf1ac..bb1929bffd 100644 --- a/rbutil/mks5lboot/mkdfu.c +++ b/rbutil/mks5lboot/mkdfu.c | |||
@@ -117,7 +117,7 @@ static void put_uint32le(unsigned char* p, uint32_t x) | |||
117 | p[3] = (x >> 24) & 0xff; | 117 | p[3] = (x >> 24) & 0xff; |
118 | } | 118 | } |
119 | 119 | ||
120 | #define ERROR(format, ...) \ | 120 | #define _ERR(format, ...) \ |
121 | do { \ | 121 | do { \ |
122 | snprintf(errstr, errstrsize, "[ERR] "format, __VA_ARGS__); \ | 122 | snprintf(errstr, errstrsize, "[ERR] "format, __VA_ARGS__); \ |
123 | goto error; \ | 123 | goto error; \ |
@@ -135,16 +135,16 @@ static unsigned char *load_file(char *filename, int *bufsize, | |||
135 | 135 | ||
136 | fd = open(filename, O_RDONLY|O_BINARY); | 136 | fd = open(filename, O_RDONLY|O_BINARY); |
137 | if (fd < 0) | 137 | if (fd < 0) |
138 | ERROR("Could not open %s for reading", filename); | 138 | _ERR("Could not open %s for reading", filename); |
139 | 139 | ||
140 | if (fstat(fd, &s) < 0) | 140 | if (fstat(fd, &s) < 0) |
141 | ERROR("Checking filesize of input file %s", filename); | 141 | _ERR("Checking filesize of input file %s", filename); |
142 | *bufsize = s.st_size; | 142 | *bufsize = s.st_size; |
143 | 143 | ||
144 | if (is_rbbl) { | 144 | if (is_rbbl) { |
145 | /* Read Rockbox header */ | 145 | /* Read Rockbox header */ |
146 | if (read(fd, header, sizeof(header)) != sizeof(header)) | 146 | if (read(fd, header, sizeof(header)) != sizeof(header)) |
147 | ERROR("Could not read file %s", filename); | 147 | _ERR("Could not read file %s", filename); |
148 | *bufsize -= sizeof(header); | 148 | *bufsize -= sizeof(header); |
149 | 149 | ||
150 | for (i = 0; i < NUM_MODELS; i++) | 150 | for (i = 0; i < NUM_MODELS; i++) |
@@ -152,7 +152,7 @@ static unsigned char *load_file(char *filename, int *bufsize, | |||
152 | break; | 152 | break; |
153 | 153 | ||
154 | if (i == NUM_MODELS) | 154 | if (i == NUM_MODELS) |
155 | ERROR("Model name \"%4.4s\" unknown. " | 155 | _ERR("Model name \"%4.4s\" unknown. " |
156 | "Is this really a rockbox bootloader?", header + 4); | 156 | "Is this really a rockbox bootloader?", header + 4); |
157 | 157 | ||
158 | *model = &ipod_identity[i]; | 158 | *model = &ipod_identity[i]; |
@@ -160,10 +160,10 @@ static unsigned char *load_file(char *filename, int *bufsize, | |||
160 | 160 | ||
161 | buf = malloc(*bufsize); | 161 | buf = malloc(*bufsize); |
162 | if (buf == NULL) | 162 | if (buf == NULL) |
163 | ERROR("Could not allocate memory for %s", filename); | 163 | _ERR("Could not allocate memory for %s", filename); |
164 | 164 | ||
165 | if (read(fd, buf, *bufsize) != *bufsize) | 165 | if (read(fd, buf, *bufsize) != *bufsize) |
166 | ERROR("Could not read file %s", filename); | 166 | _ERR("Could not read file %s", filename); |
167 | 167 | ||
168 | if (is_rbbl) { | 168 | if (is_rbbl) { |
169 | /* Check checksum */ | 169 | /* Check checksum */ |
@@ -173,7 +173,7 @@ static unsigned char *load_file(char *filename, int *bufsize, | |||
173 | sum += buf[i]; | 173 | sum += buf[i]; |
174 | } | 174 | } |
175 | if (sum != get_uint32be(header)) | 175 | if (sum != get_uint32be(header)) |
176 | ERROR("Checksum mismatch in %s", filename); | 176 | _ERR("Checksum mismatch in %s", filename); |
177 | } | 177 | } |
178 | 178 | ||
179 | close(fd); | 179 | close(fd); |
@@ -223,7 +223,7 @@ unsigned char *mkdfu(int dfu_type, char *dfu_arg, int* dfu_size, | |||
223 | } | 223 | } |
224 | } | 224 | } |
225 | if (!model) | 225 | if (!model) |
226 | ERROR("Platform name \"%s\" unknown", dfu_arg); | 226 | _ERR("Platform name \"%s\" unknown", dfu_arg); |
227 | 227 | ||
228 | *dfu_size = BIN_OFFSET + model->dualboot_uninstall_size; | 228 | *dfu_size = BIN_OFFSET + model->dualboot_uninstall_size; |
229 | dfu_desc = "BL uninstaller"; | 229 | dfu_desc = "BL uninstaller"; |
@@ -255,11 +255,11 @@ unsigned char *mkdfu(int dfu_type, char *dfu_arg, int* dfu_size, | |||
255 | } | 255 | } |
256 | 256 | ||
257 | if (*dfu_size > DFU_MAXSIZE) | 257 | if (*dfu_size > DFU_MAXSIZE) |
258 | ERROR("DFU image (%d bytes) too big", *dfu_size); | 258 | _ERR("DFU image (%d bytes) too big", *dfu_size); |
259 | 259 | ||
260 | dfu_buf = calloc(*dfu_size, 1); | 260 | dfu_buf = calloc(*dfu_size, 1); |
261 | if (!dfu_buf) | 261 | if (!dfu_buf) |
262 | ERROR("Could not allocate %d bytes for DFU image", *dfu_size); | 262 | _ERR("Could not allocate %d bytes for DFU image", *dfu_size); |
263 | 263 | ||
264 | cert_off = get_uint32le(s5l8702hdr.u.enc34.cert_off); | 264 | cert_off = get_uint32le(s5l8702hdr.u.enc34.cert_off); |
265 | cert_sz = get_uint32le(s5l8702hdr.u.enc34.cert_sz); | 265 | cert_sz = get_uint32le(s5l8702hdr.u.enc34.cert_sz); |