]>
git.zerfleddert.de Git - hmcfgusb/blob - flash-hmcfgusb.c
acf1bf6eef093faa0dcdfb1e364407dd0eed8a72
1 /* flasher for HM-CFG-USB
3 * Copyright (c) 2013 Michael Gernoth <michael@gernoth.net>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
32 #include <sys/types.h>
36 #include <libusb-1.0/libusb.h>
42 /* This might be wrong, but it works for current fw */
43 #define MAX_BLOCK_LENGTH 512
49 static int parse_hmcfgusb(uint8_t *buf
, int buf_len
, void *data
)
51 struct recv_data
*rdata
= data
;
61 static uint8_t ascii_to_nibble(uint8_t a
)
65 if ((a
>= '0') && (a
<= '9')) {
67 } else if ((a
>= 'A') && (a
<= 'F')) {
69 } else if ((a
>= 'a') && (a
<= 'f')) {
76 static int validate_nibble(uint8_t a
)
78 if (((a
>= '0') && (a
<= '9')) ||
79 ((a
>= 'A') && (a
<= 'F')) ||
80 ((a
>= 'a') && (a
<= 'f')))
86 int main(int argc
, char **argv
)
88 const char twiddlie
[] = { '-', '\\', '|', '/' };
89 struct hmcfgusb_dev
*dev
;
90 struct recv_data rdata
;
103 printf("HM-CFG-USB flasher version " VERSION
"\n\n");
107 fprintf(stderr
, "Missing firmware filename!\n\n");
109 fprintf(stderr
, "Syntax: %s hmusbif.enc\n\n", argv
[0]);
113 if (stat(argv
[1], &stat_buf
) == -1) {
114 fprintf(stderr
, "Can't stat %s: %s\n", argv
[1], strerror(errno
));
118 fd
= open(argv
[1], O_RDONLY
);
120 fprintf(stderr
, "Can't open %s: %s", argv
[1], strerror(errno
));
124 printf("Reading firmware from %s...\n", argv
[1]);
126 memset(buf
, 0, sizeof(buf
));
127 r
= read(fd
, buf
, 4);
134 printf("can't get length information!\n");
138 for (i
= 0; i
< r
; i
++) {
139 if (!validate_nibble(buf
[i
])) {
140 fprintf(stderr
, "Firmware file not valid!\n");
145 len
= (ascii_to_nibble(buf
[0]) & 0xf)<< 4;
146 len
|= ascii_to_nibble(buf
[1]) & 0xf;
148 len
|= (ascii_to_nibble(buf
[2]) & 0xf)<< 4;
149 len
|= ascii_to_nibble(buf
[3]) & 0xf;
151 /* This might be wrong, but it works for current fw */
152 if (len
> MAX_BLOCK_LENGTH
) {
153 fprintf(stderr
, "Invalid block-length %u > %u for block %d!\n", len
, MAX_BLOCK_LENGTH
, fw_blocks
+1);
157 fw
= realloc(fw
, sizeof(uint8_t*) * (fw_blocks
+ 1));
159 perror("Can't reallocate fw-blocklist");
163 fw
[fw_blocks
] = malloc(len
+ 4);
164 if (fw
[fw_blocks
] == NULL
) {
165 perror("Can't allocate memory for fw-block");
169 fw
[fw_blocks
][0] = (fw_blocks
>> 8) & 0xff;
170 fw
[fw_blocks
][1] = fw_blocks
& 0xff;
171 fw
[fw_blocks
][2] = (len
>> 8) & 0xff;
172 fw
[fw_blocks
][3] = len
& 0xff;
174 r
= read(fd
, buf
, len
* 2);
178 } else if (r
< len
* 2) {
179 fprintf(stderr
, "short read, aborting (%d < %d)\n", r
, len
* 2);
183 for (i
= 0; i
< r
; i
+=2) {
184 if ((!validate_nibble(buf
[i
])) ||
185 (!validate_nibble(buf
[i
+1]))) {
186 fprintf(stderr
, "Firmware file not valid!\n");
190 fw
[fw_blocks
][(i
/2) + 4] = (ascii_to_nibble(buf
[i
]) & 0xf)<< 4;
191 fw
[fw_blocks
][(i
/2) + 4] |= ascii_to_nibble(buf
[i
+1]) & 0xf;
196 printf("Firmware block %d with length %u read.\n", fw_blocks
, len
);
199 if (fw_blocks
== 0) {
200 fprintf(stderr
, "Firmware file not valid!\n");
204 printf("Firmware with %d blocks successfully read.\n", fw_blocks
);
206 hmcfgusb_set_debug(debug
);
208 memset(&rdata
, 0, sizeof(rdata
));
210 dev
= hmcfgusb_init(parse_hmcfgusb
, &rdata
);
212 fprintf(stderr
, "Can't initialize HM-CFG-USB\n");
216 if (!dev
->bootloader
) {
217 fprintf(stderr
, "\nHM-CFG-USB not in bootloader mode, entering bootloader.\n");
218 hmcfgusb_enter_bootloader(dev
);
219 fprintf(stderr
, "\nWaiting for device to reappear...\n");
223 } while ((dev
= hmcfgusb_init(parse_hmcfgusb
, &rdata
)) == NULL
);
225 if (!dev
->bootloader
) {
226 fprintf(stderr
, "Can't enter bootloader, giving up!\n");
231 printf("\nHM-CFG-USB opened.\n\n");
234 printf("Flasing %d blocks", fw_blocks
);
238 printf(": %c", twiddlie
[0]);
242 for (block
= 0; block
< fw_blocks
; block
++) {
243 len
= fw
[block
][2] << 8;
246 len
+= 4; /* block nr., length */
249 hexdump(fw
[block
], len
, "F> ");
252 if (!hmcfgusb_send(dev
, fw
[block
], len
, 0)) {
253 perror("\n\nhmcfgusb_send");
258 printf("Waiting for ack...\n");
261 pfd
= hmcfgusb_poll(dev
, 1);
262 if ((pfd
< 0) && errno
) {
263 perror("\n\nhmcfgusb_poll");
271 if (rdata
.ack
== 2) {
272 printf("\n\nFirmware update successfull!\n");
276 if (rdata
.ack
!= 1) {
277 fprintf(stderr
, "\n\nError flashing block %d, status: %u\n", block
, rdata
.ack
);
282 printf("\b%c", twiddlie
[block
% sizeof(twiddlie
)]);