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