blob: 7b72c66c00e3cd03371cbf2d6a06ad77afbf84b4 [file] [log] [blame]
Dave Chapman71cdf002007-10-20 09:11:34 +00001/***************************************************************************
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 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000018 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
Dave Chapman71cdf002007-10-20 09:11:34 +000022 *
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24 * KIND, either express or implied.
25 *
26 ****************************************************************************/
27
Dave Chapman71cdf002007-10-20 09:11:34 +000028#include <stdio.h>
29#include <inttypes.h>
30#include <usb.h>
31#include <string.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <unistd.h>
35#include <fcntl.h>
36
37#define VERSION "0.1"
38
Dave Chapman28c5ba82007-10-27 07:53:42 +000039#define MAX_FIRMWARESIZE (10*1024*1024) /* Arbitrary limit (for safety) */
Dave Chapman71cdf002007-10-20 09:11:34 +000040
Dave Chapman164b8f62007-10-31 17:52:50 +000041/* For win32 compatibility: */
42#ifndef O_BINARY
43#define O_BINARY 0
44#endif
45
Dave Chapman71cdf002007-10-20 09:11:34 +000046struct device_t
47{
48 char* name;
49 char* label;
Dave Chapman11251f42007-10-21 11:00:28 +000050 uint16_t productid;
Dave Chapman71cdf002007-10-20 09:11:34 +000051 uint32_t loadaddr;
Dave Chapman2c816d12007-10-20 21:00:34 +000052 uint32_t sdcfg;
Dave Chapman71cdf002007-10-20 09:11:34 +000053};
54
55static struct device_t devices[] =
56{
Dave Chapman738a8972007-10-27 11:55:38 +000057 {"c100", "Sansa C100 series", 0xb021, 0x20000000, 0x42e97010 },
Dave Chapman28c5ba82007-10-27 07:53:42 +000058 {"cowond2", "Cowon D2", 0xb011, 0x20000000, 0xa2e92010 },
Dave Chapman11251f42007-10-21 11:00:28 +000059 {"iaudio6", "iAudio 6", 0xb021, 0x20000000, 0x62e97010 },
60 {"iaudio7", "iAudio 7", 0xb021, 0x20000000, 0x62e97010 },
Dave Chapman1b39f2e2008-02-07 20:53:20 +000061 {"logikdax", "Logik DAX 1GB DAB/MP3 player", 0xb021, 0x20000000, 0x52e97410 },
Dave Chapman7d189352008-02-23 20:47:40 +000062 {"ypp2", "Samsung YP-P2", 0xb011, 0x20000000, 0x22e92010 },
Dave Chapman9ce02612008-02-23 20:50:26 +000063 {"ypk3", "Samsung YP-K3", 0xb021, 0x20000000, 0x62e92018 },
Dave Chapman71cdf002007-10-20 09:11:34 +000064};
65
66#define NUM_DEVICES ((sizeof(devices) / sizeof(struct device_t)))
67
68int find_device(char* devname)
69{
70 unsigned int i = 0;
71
72 while ((i < NUM_DEVICES) && (strcmp(devices[i].name,devname)))
73 i++;
74
75 if (i==NUM_DEVICES)
76 return -1;
77 else
78 return i;
79}
80
81void print_devices(void)
82{
83 unsigned int i;
84
85 printf("Valid devices are:\n");
86 for (i=0; i<NUM_DEVICES; i++)
87 {
88 printf(" %10s - %s\n",devices[i].name,devices[i].label);
89 }
90}
91
92/* USB IDs for USB Boot Mode */
93#define TCC_VENDORID 0x140e
Dave Chapman71cdf002007-10-20 09:11:34 +000094
95#define TCC_BULK_TO 1
96#define TOUT 5000
97#define PACKET_SIZE 64 /* Number of bytes to send in one write */
98
99#ifndef MAX
100#define MAX(a,b) (((a)>(b))?(a):(b))
101#endif
102
103static void put_int32le(uint32_t x, char* p)
104{
105 p[0] = x & 0xff;
106 p[1] = (x >> 8) & 0xff;
107 p[2] = (x >> 16) & 0xff;
108 p[3] = (x >> 24) & 0xff;
109}
110
111int upload_app(usb_dev_handle* dh, int device, char* p, int len)
112{
113 char buf[PACKET_SIZE];
114 int err;
115 int i;
116
Dave Chapman2c816d12007-10-20 21:00:34 +0000117 /* Send the header - Destination address, length and SDCFG value */
Dave Chapman71cdf002007-10-20 09:11:34 +0000118 memset(buf, 0, PACKET_SIZE);
119
120 put_int32le(0xf0000000, buf); /* Unknown - always the same */
121 put_int32le(len / PACKET_SIZE, buf + 4);
122 put_int32le(devices[device].loadaddr, buf + 8);
Dave Chapman2c816d12007-10-20 21:00:34 +0000123 put_int32le(devices[device].sdcfg, buf + 12);
Dave Chapman71cdf002007-10-20 09:11:34 +0000124
125 err = usb_bulk_write(dh, TCC_BULK_TO, buf, PACKET_SIZE, TOUT);
126
127 if (err < 0)
128 {
129 fprintf(stderr,"[ERR] Error writing header\n");
130 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
131 return -1;
132 }
133
134 /* Now send the data, PACKET_SIZE bytes at a time. */
135
136 for (i=0 ; i < (len / PACKET_SIZE) ; i++)
137 {
138 err = usb_bulk_write(dh, TCC_BULK_TO, p, PACKET_SIZE, TOUT);
139
140 if (err < 0)
141 {
142 fprintf(stderr,"[ERR] Error writing data\n");
143 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
144 return -1;
145 }
146
147 p += PACKET_SIZE;
148 }
149
150 return 0;
151}
152
153
154/* The main function */
155
156void do_patching(int device, char* buf, int len)
157{
158 struct usb_bus *busses;
159 struct usb_bus *bus;
160 struct usb_device *tmp_dev;
161 struct usb_device *dev = NULL;
162 usb_dev_handle *dh;
163 int err;
164
165 fprintf(stderr,"[INFO] Searching for TCC device...\n");
166
167 usb_init();
168 if(usb_find_busses() < 0) {
169 fprintf(stderr, "[ERR] Could not find any USB busses.\n");
170 return;
171 }
172
173 if (usb_find_devices() < 0) {
174 fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n");
175 return;
176 }
177
178 /* C calling convention, it's not nice to use global stuff */
179 busses = usb_get_busses();
180
181 for (bus = busses; bus; bus = bus->next) {
182 for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next) {
183 //printf("Found Vendor %04x Product %04x\n",tmp_dev->descriptor.idVendor, tmp_dev->descriptor.idProduct);
184 if (tmp_dev->descriptor.idVendor == TCC_VENDORID &&
Dave Chapman11251f42007-10-21 11:00:28 +0000185 tmp_dev->descriptor.idProduct == devices[device].productid) {
Dave Chapman71cdf002007-10-20 09:11:34 +0000186
187 dev = tmp_dev;
188 goto found;
189
190 }
191 }
192 }
193
194 if (dev == NULL) {
195 fprintf(stderr, "[ERR] TCC device not found.\n");
196 fprintf(stderr, "[ERR] Ensure your TCC device is in USB boot mode and run tcctool again.\n");
197 return;
198 }
199
200found:
201 if ( (dh = usb_open(dev)) == NULL) {
202 fprintf(stderr,"[ERR] Unable to open TCC device.\n");
203 return;
204 }
205
206 err = usb_set_configuration(dh, 1);
207
208 if (err < 0) {
209 fprintf(stderr, "[ERR] usb_set_configuration failed (%d)\n", err);
210 usb_close(dh);
211 return;
212 }
213
214 /* "must be called" written in the libusb documentation */
215 err = usb_claim_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
216 if (err < 0) {
217 fprintf(stderr, "[ERR] Unable to claim interface (%d)\n", err);
218 usb_close(dh);
219 return;
220 }
221
222 fprintf(stderr,"[INFO] Found TCC device, uploading application.\n");
223
224 /* Now we can transfer the application to the device. */
225
226 if (upload_app(dh, device, buf, len) < 0)
227 {
228 fprintf(stderr,"[ERR] Upload of application failed.\n");
229 }
230 else
231 {
232 fprintf(stderr,"[INFO] Patching application uploaded successfully!\n");
233 }
234
235 /* release claimed interface */
236 usb_release_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
237
238 usb_close(dh);
239}
240
241off_t filesize(int fd) {
242 struct stat buf;
243
244 if (fstat(fd,&buf) < 0) {
245 perror("[ERR] Checking filesize of input file");
246 return -1;
247 } else {
248 return(buf.st_size);
249 }
250}
251
252void print_usage(void)
253{
254 printf("Usage: tcctool -d devicename firmware.bin\n");
255}
256
257int main(int argc, char* argv[])
258{
259 char* buf;
260 int n,len;
261 int fd;
262 int device;
263
264 printf("tcctool v" VERSION " - (C) 2007 Dave Chapman\n");
265 printf("This is free software; see the source for copying conditions. There is NO\n");
266 printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
267
268 if (argc != 4)
269 {
270 print_usage();
Dave Chapman28c5ba82007-10-27 07:53:42 +0000271 print_devices();
Dave Chapman71cdf002007-10-20 09:11:34 +0000272 return 1;
273 }
274
275 if (strcmp(argv[1],"-d"))
276 {
277 print_usage();
Dave Chapman28c5ba82007-10-27 07:53:42 +0000278 print_devices();
Dave Chapman71cdf002007-10-20 09:11:34 +0000279 return 2;
280 }
281
282 device = find_device(argv[2]);
283
284 if (device < 0)
285 {
286 printf("[ERR] Unknown device \"%s\"\n",argv[2]);
287 print_devices();
288 return 3;
289 }
290
291 printf("[INFO] Using device \"%s\"\n",devices[device].label);
Dave Chapman164b8f62007-10-31 17:52:50 +0000292 fd = open(argv[3], O_RDONLY|O_BINARY);
Dave Chapman71cdf002007-10-20 09:11:34 +0000293 if (fd < 0)
294 {
295 printf("[ERR] Could not open %s\n", argv[3]);
296 return 4;
297 }
298
299 len = filesize(fd);
300
301 if (len > MAX_FIRMWARESIZE)
302 {
303 printf("[ERR] Firmware file too big\n");
304 close(fd);
305 return 5;
306 }
307
308 buf = malloc(len);
309 if (buf == NULL)
310 {
311 printf("[ERR] Could not allocate memory.\n");
312 close(fd);
313 return 6;
314 }
315
316 n = read(fd, buf, len);
317 if (n != len)
318 {
319 printf("[ERR] Short read.\n");
320 close(fd);
321 return 7;
322 }
323 close(fd);
324
325 do_patching(device, buf, len);
326
327 return 0;
328}