A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 338 lines 9.1 kB view raw
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 * 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. 22 * 23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 24 * KIND, either express or implied. 25 * 26 ****************************************************************************/ 27 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> 36 37#define MAX_FIRMWARESIZE (10*1024*1024) /* Arbitrary limit (for safety) */ 38 39/* For win32 compatibility: */ 40#ifndef O_BINARY 41#define O_BINARY 0 42#endif 43 44struct device_t 45{ 46 char* name; 47 char* label; 48 uint16_t productid; 49 uint32_t loadaddr; 50 uint32_t sdcfg; 51}; 52 53static struct device_t devices[] = 54{ 55 {"c100", "Sansa C100 series", 0xb021, 0x20000000, 0x42e97010 }, 56 {"m200", "Sansa M200 series", 0xb021, 0x20000000, 0x42e97010 }, 57 {"cowond2", "Cowon D2", 0xb011, 0x20000000, 0xa2e92010 }, 58 {"cowonj3", "Cowon J3", 0xb057, 0x20000000, 0xaaac7800 }, 59 {"cowons9", "Cowon S9", 0xb057, 0x20000000, 0xa1102800 }, 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 }, 66 {"ypt10", "Samsung YP-T10", 0xb011, 0x20000000, 0x62e97080 }, 67}; 68 69#define NUM_DEVICES ((sizeof(devices) / sizeof(struct device_t))) 70 71int find_device(char* devname) 72{ 73 unsigned int i = 0; 74 75 while ((i < NUM_DEVICES) && (strcmp(devices[i].name,devname))) 76 i++; 77 78 if (i==NUM_DEVICES) 79 return -1; 80 else 81 return i; 82} 83 84void print_devices(void) 85{ 86 unsigned int i; 87 88 printf("Valid devices are:\n"); 89 for (i=0; i<NUM_DEVICES; i++) 90 { 91 printf(" %10s - %s\n",devices[i].name,devices[i].label); 92 } 93} 94 95/* USB IDs for USB Boot Mode */ 96#define TCC_VENDORID 0x140e 97 98#define TCC_BULK_TO 1 99#define TOUT 5000 100#define PACKET_SIZE 64 /* Number of bytes to send in one write */ 101 102#ifndef MAX 103#define MAX(a,b) (((a)>(b))?(a):(b)) 104#endif 105 106static void put_int32le(uint32_t x, char* p) 107{ 108 p[0] = x & 0xff; 109 p[1] = (x >> 8) & 0xff; 110 p[2] = (x >> 16) & 0xff; 111 p[3] = (x >> 24) & 0xff; 112} 113 114int upload_app(usb_dev_handle* dh, int device, char* p, int len) 115{ 116 char buf[PACKET_SIZE]; 117 int err; 118 int i; 119 120 /* Send the header - Destination address, length and SDCFG value */ 121 memset(buf, 0, PACKET_SIZE); 122 123 put_int32le(0xf0000000, buf); /* Unknown - always the same */ 124 put_int32le(len / PACKET_SIZE, buf + 4); 125 put_int32le(devices[device].loadaddr, buf + 8); 126 put_int32le(devices[device].sdcfg, buf + 12); 127 128 err = usb_bulk_write(dh, TCC_BULK_TO, buf, PACKET_SIZE, TOUT); 129 130 if (err < 0) 131 { 132 fprintf(stderr,"[ERR] Error writing header\n"); 133 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); 134 return -1; 135 } 136 137 /* Now send the data, PACKET_SIZE bytes at a time. */ 138 139 for (i=0 ; i < (len / PACKET_SIZE) ; i++) 140 { 141 err = usb_bulk_write(dh, TCC_BULK_TO, p, PACKET_SIZE, TOUT); 142 143 if (err < 0) 144 { 145 fprintf(stderr,"[ERR] Error writing data\n"); 146 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); 147 return -1; 148 } 149 150 p += PACKET_SIZE; 151 } 152 153 return 0; 154} 155 156 157/* The main function */ 158 159int do_patching(int device, char* buf, int len) 160{ 161 struct usb_bus *busses; 162 struct usb_bus *bus; 163 struct usb_device *tmp_dev; 164 struct usb_device *dev = NULL; 165 usb_dev_handle *dh; 166 int err; 167 168 fprintf(stderr,"[INFO] Searching for TCC device...\n"); 169 170 usb_init(); 171 if(usb_find_busses() < 0) { 172 fprintf(stderr, "[ERR] Could not find any USB busses.\n"); 173 return -1; 174 } 175 176 if (usb_find_devices() < 0) { 177 fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n"); 178 return -1; 179 } 180 181 /* C calling convention, it's not nice to use global stuff */ 182 busses = usb_get_busses(); 183 184 for (bus = busses; bus; bus = bus->next) { 185 for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next) { 186 //printf("Found Vendor %04x Product %04x\n",tmp_dev->descriptor.idVendor, tmp_dev->descriptor.idProduct); 187 if (tmp_dev->descriptor.idVendor == TCC_VENDORID && 188 tmp_dev->descriptor.idProduct == devices[device].productid) { 189 190 dev = tmp_dev; 191 goto found; 192 193 } 194 } 195 } 196 197 if (dev == NULL) { 198 fprintf(stderr, "[ERR] TCC device not found.\n"); 199 fprintf(stderr, "[ERR] Ensure your TCC device is in USB boot mode and run tcctool again.\n"); 200 return -1; 201 } 202 203found: 204 if ( (dh = usb_open(dev)) == NULL) { 205 fprintf(stderr,"[ERR] Unable to open TCC device.\n"); 206 return -1; 207 } 208 209 err = usb_set_configuration(dh, 1); 210 211 if (err < 0) { 212 fprintf(stderr, "[ERR] usb_set_configuration failed (%d)\n", err); 213 usb_close(dh); 214 return -1; 215 } 216 217 /* "must be called" written in the libusb documentation */ 218 err = usb_claim_interface(dh, dev->config->interface->altsetting->bInterfaceNumber); 219 if (err < 0) { 220 fprintf(stderr, "[ERR] Unable to claim interface (%d)\n", err); 221 usb_close(dh); 222 return -1; 223 } 224 225 fprintf(stderr,"[INFO] Found TCC device, uploading application.\n"); 226 227 /* Now we can transfer the application to the device. */ 228 229 if ( (err = upload_app(dh, device, buf, len)) < 0) 230 { 231 fprintf(stderr,"[ERR] Upload of application failed.\n"); 232 } 233 else 234 { 235 fprintf(stderr,"[INFO] Patching application uploaded successfully!\n"); 236 } 237 238 /* release claimed interface */ 239 usb_release_interface(dh, dev->config->interface->altsetting->bInterfaceNumber); 240 usb_close(dh); 241 242 return err < 0 ? -1: 0; 243} 244 245off_t filesize(int fd) { 246 struct stat buf; 247 248 if (fstat(fd,&buf) < 0) { 249 perror("[ERR] Checking filesize of input file"); 250 return -1; 251 } else { 252 return(buf.st_size); 253 } 254} 255 256void print_usage(void) 257{ 258 printf("Usage: tcctool -d devicename firmware.bin\n"); 259} 260 261int main(int argc, char* argv[]) 262{ 263 char* buf; 264 int n,len,padded_len; 265 int fd; 266 int device; 267 268 printf("tcctool " VERSION " - (C) 2007-2010 Dave Chapman\n"); 269 printf("This is free software; see the source for copying conditions. There is NO\n"); 270 printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); 271 272 if (argc != 4) 273 { 274 print_usage(); 275 print_devices(); 276 return 1; 277 } 278 279 if (strcmp(argv[1],"-d")) 280 { 281 print_usage(); 282 print_devices(); 283 return 2; 284 } 285 286 device = find_device(argv[2]); 287 288 if (device < 0) 289 { 290 printf("[ERR] Unknown device \"%s\"\n",argv[2]); 291 print_devices(); 292 return 3; 293 } 294 295 printf("[INFO] Using device \"%s\"\n",devices[device].label); 296 fd = open(argv[3], O_RDONLY|O_BINARY); 297 if (fd < 0) 298 { 299 printf("[ERR] Could not open %s\n", argv[3]); 300 return 4; 301 } 302 303 len = filesize(fd); 304 305 if (len > MAX_FIRMWARESIZE) 306 { 307 printf("[ERR] Firmware file too big\n"); 308 close(fd); 309 return 5; 310 } 311 312 /* Round len up to multiple of PACKET_SIZE */ 313 padded_len = (len + PACKET_SIZE) & ~(PACKET_SIZE-1); 314 315 buf = malloc(padded_len); 316 if (buf == NULL) 317 { 318 printf("[ERR] Could not allocate memory.\n"); 319 close(fd); 320 return 6; 321 } 322 323 n = read(fd, buf, len); 324 if (n != len) 325 { 326 printf("[ERR] Short read.\n"); 327 close(fd); 328 return 7; 329 } 330 close(fd); 331 332 if (do_patching(device, buf, padded_len)) 333 { 334 return 8; 335 } 336 337 return 0; 338}