summaryrefslogtreecommitdiff
path: root/utils/tcctool/tcctool.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/tcctool/tcctool.c')
-rw-r--r--utils/tcctool/tcctool.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/utils/tcctool/tcctool.c b/utils/tcctool/tcctool.c
new file mode 100644
index 0000000000..22e6f1066d
--- /dev/null
+++ b/utils/tcctool/tcctool.c
@@ -0,0 +1,316 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Dave Chapman
11 *
12 * USB code based on ifp-line - http://ifp-driver.sourceforge.net
13 *
14 * ifp-line is (C) Pavel Kriz, Jun Yamishiro and Joe Roback and
15 * licensed under the GPL (v2)
16 *
17 *
18 * All files in this archive are subject to the GNU General Public License.
19 * See the file COPYING in the source tree root for full license agreement.
20 *
21 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22 * KIND, either express or implied.
23 *
24 ****************************************************************************/
25
26
27#include <stdio.h>
28#include <inttypes.h>
29#include <usb.h>
30#include <string.h>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <unistd.h>
34#include <fcntl.h>
35
36#define VERSION "0.1"
37
38#define MAX_FIRMWARESIZE (2*1024*1024) /* Arbitrary limit (for safety) */
39
40struct device_t
41{
42 char* name;
43 char* label;
44 uint32_t loadaddr;
45 uint32_t magic;
46};
47
48static struct device_t devices[] =
49{
50 {"logikdax", "Logik DAX 1GB DAB/MP3 player", 0x20000000, 0x52e97410 },
51 {"iaudio6", "iAudio 6", 0x20000000, 0x62e97010 },
52 {"iaudio7", "iAudio 7", 0x20000000, 0x62e97010 }
53};
54
55#define NUM_DEVICES ((sizeof(devices) / sizeof(struct device_t)))
56
57int find_device(char* devname)
58{
59 unsigned int i = 0;
60
61 while ((i < NUM_DEVICES) && (strcmp(devices[i].name,devname)))
62 i++;
63
64 if (i==NUM_DEVICES)
65 return -1;
66 else
67 return i;
68}
69
70void print_devices(void)
71{
72 unsigned int i;
73
74 printf("Valid devices are:\n");
75 for (i=0; i<NUM_DEVICES; i++)
76 {
77 printf(" %10s - %s\n",devices[i].name,devices[i].label);
78 }
79}
80
81/* USB IDs for USB Boot Mode */
82#define TCC_VENDORID 0x140e
83#define TCC_PRODUCTID 0xb021
84
85#define TCC_BULK_TO 1
86#define TOUT 5000
87#define PACKET_SIZE 64 /* Number of bytes to send in one write */
88
89#ifndef MAX
90#define MAX(a,b) (((a)>(b))?(a):(b))
91#endif
92
93static void put_int32le(uint32_t x, char* p)
94{
95 p[0] = x & 0xff;
96 p[1] = (x >> 8) & 0xff;
97 p[2] = (x >> 16) & 0xff;
98 p[3] = (x >> 24) & 0xff;
99}
100
101int upload_app(usb_dev_handle* dh, int device, char* p, int len)
102{
103 char buf[PACKET_SIZE];
104 int err;
105 int i;
106
107 /* Send the header - Destination address, length and magic value */
108 memset(buf, 0, PACKET_SIZE);
109
110 put_int32le(0xf0000000, buf); /* Unknown - always the same */
111 put_int32le(len / PACKET_SIZE, buf + 4);
112 put_int32le(devices[device].loadaddr, buf + 8);
113 put_int32le(devices[device].magic, buf + 12);
114
115 err = usb_bulk_write(dh, TCC_BULK_TO, buf, PACKET_SIZE, TOUT);
116
117 if (err < 0)
118 {
119 fprintf(stderr,"[ERR] Error writing header\n");
120 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
121 return -1;
122 }
123
124 /* Now send the data, PACKET_SIZE bytes at a time. */
125
126 for (i=0 ; i < (len / PACKET_SIZE) ; i++)
127 {
128 err = usb_bulk_write(dh, TCC_BULK_TO, p, PACKET_SIZE, TOUT);
129
130 if (err < 0)
131 {
132 fprintf(stderr,"[ERR] Error writing data\n");
133 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
134 return -1;
135 }
136
137 p += PACKET_SIZE;
138 }
139
140 return 0;
141}
142
143
144/* The main function */
145
146void do_patching(int device, char* buf, int len)
147{
148 struct usb_bus *busses;
149 struct usb_bus *bus;
150 struct usb_device *tmp_dev;
151 struct usb_device *dev = NULL;
152 usb_dev_handle *dh;
153 int err;
154
155 fprintf(stderr,"[INFO] Searching for TCC device...\n");
156
157 usb_init();
158 if(usb_find_busses() < 0) {
159 fprintf(stderr, "[ERR] Could not find any USB busses.\n");
160 return;
161 }
162
163 if (usb_find_devices() < 0) {
164 fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n");
165 return;
166 }
167
168 /* C calling convention, it's not nice to use global stuff */
169 busses = usb_get_busses();
170
171 for (bus = busses; bus; bus = bus->next) {
172 for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next) {
173 //printf("Found Vendor %04x Product %04x\n",tmp_dev->descriptor.idVendor, tmp_dev->descriptor.idProduct);
174 if (tmp_dev->descriptor.idVendor == TCC_VENDORID &&
175 tmp_dev->descriptor.idProduct == TCC_PRODUCTID ) {
176
177 dev = tmp_dev;
178 goto found;
179
180 }
181 }
182 }
183
184 if (dev == NULL) {
185 fprintf(stderr, "[ERR] TCC device not found.\n");
186 fprintf(stderr, "[ERR] Ensure your TCC device is in USB boot mode and run tcctool again.\n");
187 return;
188 }
189
190found:
191 if ( (dh = usb_open(dev)) == NULL) {
192 fprintf(stderr,"[ERR] Unable to open TCC device.\n");
193 return;
194 }
195
196 err = usb_set_configuration(dh, 1);
197
198 if (err < 0) {
199 fprintf(stderr, "[ERR] usb_set_configuration failed (%d)\n", err);
200 usb_close(dh);
201 return;
202 }
203
204 /* "must be called" written in the libusb documentation */
205 err = usb_claim_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
206 if (err < 0) {
207 fprintf(stderr, "[ERR] Unable to claim interface (%d)\n", err);
208 usb_close(dh);
209 return;
210 }
211
212 fprintf(stderr,"[INFO] Found TCC device, uploading application.\n");
213
214 /* Now we can transfer the application to the device. */
215
216 if (upload_app(dh, device, buf, len) < 0)
217 {
218 fprintf(stderr,"[ERR] Upload of application failed.\n");
219 }
220 else
221 {
222 fprintf(stderr,"[INFO] Patching application uploaded successfully!\n");
223 }
224
225 /* release claimed interface */
226 usb_release_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
227
228 usb_close(dh);
229}
230
231off_t filesize(int fd) {
232 struct stat buf;
233
234 if (fstat(fd,&buf) < 0) {
235 perror("[ERR] Checking filesize of input file");
236 return -1;
237 } else {
238 return(buf.st_size);
239 }
240}
241
242void print_usage(void)
243{
244 printf("Usage: tcctool -d devicename firmware.bin\n");
245}
246
247int main(int argc, char* argv[])
248{
249 char* buf;
250 int n,len;
251 int fd;
252 int device;
253
254 printf("tcctool v" VERSION " - (C) 2007 Dave Chapman\n");
255 printf("This is free software; see the source for copying conditions. There is NO\n");
256 printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
257
258 if (argc != 4)
259 {
260 print_usage();
261 return 1;
262 }
263
264 if (strcmp(argv[1],"-d"))
265 {
266 print_usage();
267 return 2;
268 }
269
270 device = find_device(argv[2]);
271
272 if (device < 0)
273 {
274 printf("[ERR] Unknown device \"%s\"\n",argv[2]);
275 print_devices();
276 return 3;
277 }
278
279 printf("[INFO] Using device \"%s\"\n",devices[device].label);
280 fd = open(argv[3], O_RDONLY);
281 if (fd < 0)
282 {
283 printf("[ERR] Could not open %s\n", argv[3]);
284 return 4;
285 }
286
287 len = filesize(fd);
288
289 if (len > MAX_FIRMWARESIZE)
290 {
291 printf("[ERR] Firmware file too big\n");
292 close(fd);
293 return 5;
294 }
295
296 buf = malloc(len);
297 if (buf == NULL)
298 {
299 printf("[ERR] Could not allocate memory.\n");
300 close(fd);
301 return 6;
302 }
303
304 n = read(fd, buf, len);
305 if (n != len)
306 {
307 printf("[ERR] Short read.\n");
308 close(fd);
309 return 7;
310 }
311 close(fd);
312
313 do_patching(device, buf, len);
314
315 return 0;
316}