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