summaryrefslogtreecommitdiffstats
path: root/utils/e200rpatcher/e200rpatcher.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/e200rpatcher/e200rpatcher.c')
-rw-r--r--utils/e200rpatcher/e200rpatcher.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/utils/e200rpatcher/e200rpatcher.c b/utils/e200rpatcher/e200rpatcher.c
new file mode 100644
index 0000000000..be09370997
--- /dev/null
+++ b/utils/e200rpatcher/e200rpatcher.c
@@ -0,0 +1,241 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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)
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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 <string.h>
+#include "stdbool.h"
+
+#include "bootimg.h"
+
+#define VERSION "0.2"
+
+/* 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");
+ fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
+ 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");
+ fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
+ 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;
+ int err;
+
+ 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();
+
+ 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;
+ }
+
+ err = usb_set_configuration(dh, 1);
+
+ if (err < 0) {
+ fprintf(stderr, "[ERR] usb_set_configuration failed (%d)\n", err);
+ usb_close(dh);
+ return;
+ }
+
+ /* "must be called" written in the libusb documentation */
+ err = usb_claim_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
+ if (err < 0) {
+ fprintf(stderr, "[ERR] Unable to claim interface (%d)\n", err);
+ usb_close(dh);
+ return;
+ }
+
+ fprintf(stderr,"[INFO] 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);
+}
+void print_usage(void)
+{
+ fprintf(stderr,"Usage: e200rpatcher [options]\n");
+ fprintf(stderr,"Options:\n");
+ fprintf(stderr," -s, --silent\t\tDont display instructions\n");
+}
+
+int main(int argc, char* argv[])
+{
+ char input[4];
+ int silent = 0;
+ int i;
+
+ /* check args */
+ if ((argc > 1) && ((strcmp(argv[1],"-h")==0) || (strcmp(argv[1],"--help")==0))) {
+ print_usage();
+ return 1;
+ }
+ for (i=1;i<argc;i++)
+ {
+ if (!strcmp(argv[i], "--silent") || !strcmp(argv[i], "-s"))
+ silent = 1;
+ }
+
+ 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");
+
+ if (!silent)
+ {
+ 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();
+
+ if (!silent)
+ {
+ printf("[INFO] Press ENTER to exit: ");
+ fgets(input, 4, stdin);
+ }
+
+ return 0;
+}