
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>

#include <usb.h> /* This tool requires libusb */


#define E200_INTERFACE 0
#define E200_ENDPOINT  1

#define E200_TIMEOUT    5000
#define PROGRAM_TIMEOUT 120000

#define SANDISK_VENDOR_ID  0x0781
#define SANDISK_PRODUCT_ID 0x0720
#define PP_VENDOR_ID       0x0b70
#define PP_PRODUCT_ID      0x0003

#define BUFSIZE 64

char buffer[BUFSIZE];

#undef  MIN
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#if defined(YourArchHere)
void
do_delay(int secs)
{
}
#else /* POSIX */
#include <unistd.h>
void
do_delay(int secs)
{
  sleep(secs);
}
#endif

void
put_le32(void * ptr, uint32_t val)
{
  uint8_t * b = ptr;

  b[0] = val;
  b[1] = val >> 8;
  b[2] = val >> 16;
  b[3] = val >> 24;
}


int
send_dev(usb_dev_handle * ud, const void * data, uint32_t len)
{
  char * buf = (char *)data;
  int32_t todo;
  int ret;

  while (len > 0) {
    todo = len > BUFSIZE ? BUFSIZE : len;

    ret = usb_bulk_write(ud, E200_ENDPOINT, buf, todo, E200_TIMEOUT);

    if (ret < 0) {
      fprintf(stderr, "\nBulk write error (%d, %s)\n", ret, strerror(-ret));
      return ret;
    }

    buf += ret;
    len -= ret;
  }

  return 0;
}

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int read_custom (char *filename, unsigned char *buf, int buf_len)
{
    int ret;
    int fd = open(filename, O_RDONLY);
    if (fd < 0)
    {
        printf("couldnt open %s\n", filename);
        exit(1);
    }
    ret = read(fd, buf, buf_len);
    close(fd);
    return ret;
}

int
device_match(struct usb_device * dev, int vendor, int product)
{
  return (dev->descriptor.idVendor        == vendor &&
	  dev->descriptor.idProduct       == product &&
	  dev->descriptor.bDeviceClass    == 0xff &&
	  dev->descriptor.bDeviceSubClass == 0xff &&
	  dev->descriptor.bDeviceProtocol == 0xff);
}
usb_dev_handle *
device_get(int vendor, int product)
{
  struct usb_bus * bus, * busses;
  struct usb_device * dev;
  usb_dev_handle * ud;
  int ret, retries = 10;

  fprintf(stderr, "Searching for device %04x:%04x ... ", vendor, product);

 retry:

  usb_find_busses();
  usb_find_devices();

  busses = usb_get_busses();

  for (bus = busses; bus; bus = bus->next) {
    for (dev = bus->devices; dev; dev = dev->next) {
      if (!device_match(dev, vendor, product)) {
	continue;
      }

      fprintf(stderr, "found!\n");

      ud = usb_open(dev);

      if (!ud) {
	fprintf(stderr, "Failed to open the device!\n");
	return NULL;
      }

      ret = usb_claim_interface(ud, E200_INTERFACE);

      if (ret < 0) {
	fprintf(stderr, "Failed to claim the interface (%d, %s)\n",
		ret, strerror(-ret));
	usb_close(ud);

	return NULL;
      }

      return ud;
    }
  }

  if (retries-- > 0) {
    do_delay(1);
    fprintf(stderr, "%d ", retries);
    goto retry;
  }

  fprintf(stderr, "not found!\n");

  return NULL;
}

int
device_release(usb_dev_handle * ud)
{
  usb_release_interface(ud, E200_INTERFACE);

  return usb_close(ud);
}

int
cmd_init(char *filename)
{
  unsigned char custom[128*1024];
  uint32_t custom_len;
  usb_dev_handle * ud;
  int ret;

  ret = read_custom(filename, custom, 128*1024);
  if (ret < 1)
  {
    printf("error: %d\n", custom_len);
    exit(1);
    }
    custom_len = ret;
  ud = device_get(SANDISK_VENDOR_ID, SANDISK_PRODUCT_ID);

  if (!ud) {
    ud = device_get(PP_VENDOR_ID, PP_PRODUCT_ID);
    if (!ud) {
      exit(1);
    }
  }

  fprintf(stderr, "Initializing USB stub (%d bytes) ... ", custom_len);
//custom_len = 64*1024 -1;
  put_le32(buffer, custom_len);
  
  ret = usb_bulk_write(ud, E200_ENDPOINT, buffer, sizeof(custom_len), E200_TIMEOUT);
  if (ret < 0) {
    fprintf(stderr, "\nLength write error (%d, %s)\n", ret, strerror(-ret));
    exit(1);
  }

  ret = send_dev(ud, custom, custom_len);
fprintf(stderr,"written %d bytes\n", custom_len);

  if (ret < 0) {
    exit(1);
  }

  fprintf(stderr, "done!\n");

  device_release(ud);

  return 0;
}

int
main(int argc, char * argv[])
{

  fprintf(stderr, "e200tool-slim origionally (c) by MrH 2006, 2007, modified by me\n");
  if (argc < 2)
  {
    printf("Usage: %s file\n", argv[0]);
    return 0;
  }
  usb_init();


  return cmd_init(argv[1]);
}
