Fix the pitch detector plugin for iaudioM3
[kugel-rb.git] / utils / tcctool / tcctool.c
blob9c5222603d3c7214a69656ac74eefe0d45c4bef3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Dave Chapman
12 * USB code based on ifp-line - http://ifp-driver.sourceforge.net
14 * ifp-line is (C) Pavel Kriz, Jun Yamishiro and Joe Roback and
15 * licensed under the GPL (v2)
18 * 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.
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24 * KIND, either express or implied.
26 ****************************************************************************/
28 #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>
37 #define VERSION "0.1"
39 #define MAX_FIRMWARESIZE (10*1024*1024) /* Arbitrary limit (for safety) */
41 /* For win32 compatibility: */
42 #ifndef O_BINARY
43 #define O_BINARY 0
44 #endif
46 struct device_t
48 char* name;
49 char* label;
50 uint16_t productid;
51 uint32_t loadaddr;
52 uint32_t sdcfg;
55 static struct device_t devices[] =
57 {"c100", "Sansa C100 series", 0xb021, 0x20000000, 0x42e97010 },
58 {"m200", "Sansa M200 series", 0xb021, 0x20000000, 0x42e97010 },
59 {"cowond2", "Cowon D2", 0xb011, 0x20000000, 0xa2e92010 },
60 {"iaudio6", "iAudio 6", 0xb021, 0x20000000, 0x62e97010 },
61 {"iaudio7", "iAudio 7", 0xb021, 0x20000000, 0x62e97010 },
62 {"logikdax", "Logik DAX 1GB DAB/MP3 player", 0xb021, 0x20000000, 0x52e97410 },
63 {"x20", "iRiver X20", 0xb051, 0x20000000, 0x02e92010 },
64 {"ypp2", "Samsung YP-P2", 0xb011, 0x20000000, 0x22e92010 },
65 {"ypk3", "Samsung YP-K3", 0xb021, 0x20000000, 0x62e92018 },
68 #define NUM_DEVICES ((sizeof(devices) / sizeof(struct device_t)))
70 int find_device(char* devname)
72 unsigned int i = 0;
74 while ((i < NUM_DEVICES) && (strcmp(devices[i].name,devname)))
75 i++;
77 if (i==NUM_DEVICES)
78 return -1;
79 else
80 return i;
83 void print_devices(void)
85 unsigned int i;
87 printf("Valid devices are:\n");
88 for (i=0; i<NUM_DEVICES; i++)
90 printf(" %10s - %s\n",devices[i].name,devices[i].label);
94 /* USB IDs for USB Boot Mode */
95 #define TCC_VENDORID 0x140e
97 #define TCC_BULK_TO 1
98 #define TOUT 5000
99 #define PACKET_SIZE 64 /* Number of bytes to send in one write */
101 #ifndef MAX
102 #define MAX(a,b) (((a)>(b))?(a):(b))
103 #endif
105 static void put_int32le(uint32_t x, char* p)
107 p[0] = x & 0xff;
108 p[1] = (x >> 8) & 0xff;
109 p[2] = (x >> 16) & 0xff;
110 p[3] = (x >> 24) & 0xff;
113 int upload_app(usb_dev_handle* dh, int device, char* p, int len)
115 char buf[PACKET_SIZE];
116 int err;
117 int i;
119 /* Send the header - Destination address, length and SDCFG value */
120 memset(buf, 0, PACKET_SIZE);
122 put_int32le(0xf0000000, buf); /* Unknown - always the same */
123 put_int32le(len / PACKET_SIZE, buf + 4);
124 put_int32le(devices[device].loadaddr, buf + 8);
125 put_int32le(devices[device].sdcfg, buf + 12);
127 err = usb_bulk_write(dh, TCC_BULK_TO, buf, PACKET_SIZE, TOUT);
129 if (err < 0)
131 fprintf(stderr,"[ERR] Error writing header\n");
132 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
133 return -1;
136 /* Now send the data, PACKET_SIZE bytes at a time. */
138 for (i=0 ; i < (len / PACKET_SIZE) ; i++)
140 err = usb_bulk_write(dh, TCC_BULK_TO, p, PACKET_SIZE, TOUT);
142 if (err < 0)
144 fprintf(stderr,"[ERR] Error writing data\n");
145 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
146 return -1;
149 p += PACKET_SIZE;
152 return 0;
156 /* The main function */
158 int do_patching(int device, char* buf, int len)
160 struct usb_bus *busses;
161 struct usb_bus *bus;
162 struct usb_device *tmp_dev;
163 struct usb_device *dev = NULL;
164 usb_dev_handle *dh;
165 int err;
167 fprintf(stderr,"[INFO] Searching for TCC device...\n");
169 usb_init();
170 if(usb_find_busses() < 0) {
171 fprintf(stderr, "[ERR] Could not find any USB busses.\n");
172 return -1;
175 if (usb_find_devices() < 0) {
176 fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n");
177 return -1;
180 /* C calling convention, it's not nice to use global stuff */
181 busses = usb_get_busses();
183 for (bus = busses; bus; bus = bus->next) {
184 for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next) {
185 //printf("Found Vendor %04x Product %04x\n",tmp_dev->descriptor.idVendor, tmp_dev->descriptor.idProduct);
186 if (tmp_dev->descriptor.idVendor == TCC_VENDORID &&
187 tmp_dev->descriptor.idProduct == devices[device].productid) {
189 dev = tmp_dev;
190 goto found;
196 if (dev == NULL) {
197 fprintf(stderr, "[ERR] TCC device not found.\n");
198 fprintf(stderr, "[ERR] Ensure your TCC device is in USB boot mode and run tcctool again.\n");
199 return -1;
202 found:
203 if ( (dh = usb_open(dev)) == NULL) {
204 fprintf(stderr,"[ERR] Unable to open TCC device.\n");
205 return -1;
208 err = usb_set_configuration(dh, 1);
210 if (err < 0) {
211 fprintf(stderr, "[ERR] usb_set_configuration failed (%d)\n", err);
212 usb_close(dh);
213 return -1;
216 /* "must be called" written in the libusb documentation */
217 err = usb_claim_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
218 if (err < 0) {
219 fprintf(stderr, "[ERR] Unable to claim interface (%d)\n", err);
220 usb_close(dh);
221 return -1;
224 fprintf(stderr,"[INFO] Found TCC device, uploading application.\n");
226 /* Now we can transfer the application to the device. */
228 if ( (err = upload_app(dh, device, buf, len)) < 0)
230 fprintf(stderr,"[ERR] Upload of application failed.\n");
232 else
234 fprintf(stderr,"[INFO] Patching application uploaded successfully!\n");
237 /* release claimed interface */
238 usb_release_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
239 usb_close(dh);
241 return err < 0 ? -1: 0;
244 off_t filesize(int fd) {
245 struct stat buf;
247 if (fstat(fd,&buf) < 0) {
248 perror("[ERR] Checking filesize of input file");
249 return -1;
250 } else {
251 return(buf.st_size);
255 void print_usage(void)
257 printf("Usage: tcctool -d devicename firmware.bin\n");
260 int main(int argc, char* argv[])
262 char* buf;
263 int n,len,padded_len;
264 int fd;
265 int device;
267 printf("tcctool v" VERSION " - (C) 2007 Dave Chapman\n");
268 printf("This is free software; see the source for copying conditions. There is NO\n");
269 printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
271 if (argc != 4)
273 print_usage();
274 print_devices();
275 return 1;
278 if (strcmp(argv[1],"-d"))
280 print_usage();
281 print_devices();
282 return 2;
285 device = find_device(argv[2]);
287 if (device < 0)
289 printf("[ERR] Unknown device \"%s\"\n",argv[2]);
290 print_devices();
291 return 3;
294 printf("[INFO] Using device \"%s\"\n",devices[device].label);
295 fd = open(argv[3], O_RDONLY|O_BINARY);
296 if (fd < 0)
298 printf("[ERR] Could not open %s\n", argv[3]);
299 return 4;
302 len = filesize(fd);
304 if (len > MAX_FIRMWARESIZE)
306 printf("[ERR] Firmware file too big\n");
307 close(fd);
308 return 5;
311 /* Round len up to multiple of PACKET_SIZE */
312 padded_len = (len + PACKET_SIZE) & ~(PACKET_SIZE-1);
314 buf = malloc(padded_len);
315 if (buf == NULL)
317 printf("[ERR] Could not allocate memory.\n");
318 close(fd);
319 return 6;
322 n = read(fd, buf, len);
323 if (n != len)
325 printf("[ERR] Short read.\n");
326 close(fd);
327 return 7;
329 close(fd);
331 if (do_patching(device, buf, padded_len))
333 return 8;
336 return 0;