diff options
Diffstat (limited to 'rbutil/e200rpatcher/e200rpatcher.c')
-rw-r--r-- | rbutil/e200rpatcher/e200rpatcher.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/rbutil/e200rpatcher/e200rpatcher.c b/rbutil/e200rpatcher/e200rpatcher.c new file mode 100644 index 0000000000..a2531e9f6d --- /dev/null +++ b/rbutil/e200rpatcher/e200rpatcher.c @@ -0,0 +1,211 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 Dave Chapman + * + * USB code based on ifp-line - http://ifp-driver.sourceforge.net + * + * ifp-line is (C) Pavel Kriz, Jun Yamishiro and Joe Roback and + * licensed under the GPL (v2) + * + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + + +#include <stdio.h> +#include <inttypes.h> +#include <usb.h> + +#include "bootimg.h" + +#define VERSION "0.1-svn" + +/* USB IDs for Manufacturing Mode */ +#define E200R_VENDORID 0x0781 +#define E200R_PRODUCTID 0x0720 + +#define E200R_BULK_TO 1 +#define TOUT 5000 +#define MAX_TRANSFER 64 /* Number of bytes to send in one write */ + +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +static void put_int32le(uint32_t x, char* p) +{ + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; +} + +int upload_app(usb_dev_handle* dh) +{ + char buf[4]; + int err; + int tosend; + char* p = (char*)bootimg; + int bytesleft = LEN_bootimg; + + /* Write the data length */ + + put_int32le(LEN_bootimg, buf); + + err = usb_bulk_write(dh, E200R_BULK_TO, buf, 4, TOUT); + + if (err < 0) + { + fprintf(stderr,"[ERR] Error writing data length\n"); + return -1; + } + + /* Now send the data, MAX_TRANSFER bytes at a time. */ + + while (bytesleft > 0) + { + tosend = MAX(MAX_TRANSFER, bytesleft); + + err = usb_bulk_write(dh, E200R_BULK_TO, p, tosend, TOUT); + + if (err < 0) + { + fprintf(stderr,"[ERR] Error writing data\n"); + return -1; + } + + p += tosend; + bytesleft -= tosend; + } + + return 0; +} + + +/* The main function */ + +void do_patching(void) +{ + struct usb_bus *busses; + struct usb_bus *bus; + struct usb_device *tmp_dev; + struct usb_device *dev = NULL; + usb_dev_handle *dh; + + fprintf(stderr,"[INFO] Searching for E200R\n"); + + usb_init(); + + if(usb_find_busses() < 0) { + fprintf(stderr, "[ERR] Could not find any USB busses.\n"); + return; + } + + if (usb_find_devices() < 0) { + fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n"); + return; + } + + /* C calling convention, it's not nice to use global stuff */ + busses = usb_get_busses(); + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + for (bus = busses; bus; bus = bus->next) { + for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next) { + if (tmp_dev->descriptor.idVendor == E200R_VENDORID && + tmp_dev->descriptor.idProduct == E200R_PRODUCTID ) { + + dev = tmp_dev; + goto found; + + } + } + } + + if (dev == NULL) { + fprintf(stderr, "[ERR] E200R device not found.\n"); + fprintf(stderr, "[ERR] Ensure your E200R is in manufacturing mode and run e200rpatcher again.\n"); + return; + } + +found: + if ( (dh = usb_open(dev)) == NULL) { + fprintf(stderr,"[ERR] Unable to open E200R device.\n"); + return; + } + + /* "must be called" written in the libusb documentation */ + if (usb_claim_interface(dh, dev->config->interface->altsetting->bInterfaceNumber)) { + fprintf(stderr, "[ERR] Device is busy. (I was unable to claim its interface.)\n"); + usb_close(dh); + return; + } + + + fprintf(stderr,"[ERR] Found E200R, uploading patching application.\n"); + + /* Now we can transfer the application to the device. */ + + if (upload_app(dh) < 0) + { + fprintf(stderr,"[ERR] Upload of application failed.\n"); + } + else + { + fprintf(stderr,"[INFO] Patching application uploaded successfully!\n"); + } + + /* release claimed interface */ + usb_release_interface(dh, dev->config->interface->altsetting->bInterfaceNumber); + + usb_close(dh); +} + + +int main(int argc, char* argv[]) +{ + char input[4]; + + /* We don't use the arguments */ + (void)argc; + (void)argv; + + printf("e200rpatcher v" VERSION " - (C) 2007 Jonathan Gordon & Dave Chapman\n"); + printf("This is free software; see the source for copying conditions. There is NO\n"); + printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); + + printf("Attach your E200R in \"manufacturing mode\" as follows:\n"); + printf(" 1) Power-off your E200R\n"); + printf(" 2) Turn ON the lock/hold switch\n"); + printf(" 3) Press and hold the SELECT button and whilst it is held down,\n"); + printf(" attach your E200R to your computer via USB\n"); + printf(" 4) After attaching to USB, keep the SELECT button held for 10 seconds.\n"); + printf("\n"); + printf("NOTE: If your E200R starts in the normal Sansa firmware, you have\n"); + printf(" failed to enter manufacturing mode and should try again at step 1).\n\n"); + + printf("[INFO] Press Enter to continue:"); + fgets(input, 4, stdin); + + do_patching(); + + printf("[INFO] Press ENTER to exit: "); + fgets(input, 4, stdin); + + return 0; +} |