view minimon.c @ 6:3819ecaf0f14

avoiding clash with latest libjpeg
author Peter Meerwald <pmeerw@pmeerw.net>
date Tue, 10 May 2011 19:10:18 +0200
parents bac8ed8d6eb9
children 078dc69945ad
line wrap: on
line source

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include "usb.h"

static const char *progname = "minimon";

static int need_switch = 0;
static int have_idx = -1;

typedef struct {
  int mass_id;
  int custom_id;
  const char *name;
  int width;
  int height;
} id_info_t;

// there are many more, 
static id_info_t ids[] = {
  {0x2027, 0x2028, "SPF-107H", 1024, 600},
  {0xffff, 0xffff, "SPF-75H", 800, 480}, 
  {0xffff, 0xffff, "SPF-83H", 800, 600}, 
  {0xffff, 0xffff, "SPF-85H", 800, 600}, // 85P??
  {0x2033, 0x2034, "SPF-87H", 800, 480},  
  {0x2035, 0x2036, "SPF-107H", 1024, 600},  
  {0, 0, } // end-of-list
};

static int in_list(int id, id_info_t *list) {
  if (!list) 
    return 0;

  int idx = 0;
  while (list->mass_id || list->custom_id) {
    if (id == list->mass_id) {
      // still in mass-storage mode, need to switch
      need_switch = 1; 
      return idx;
    }
    else if (id == list->custom_id) {
      need_switch = 0;
      return idx;
    }
    idx++;
    list++;
  }

  return -1;
}

static struct usb_device *find_dev() {
  struct usb_bus *bus;
  struct usb_device *dev;

  usb_init();
  usb_find_busses();
  usb_find_devices();

  for (bus = usb_busses; bus; bus = bus->next) {
    for (dev = bus->devices; dev; dev = dev->next) {
      if (dev->descriptor.idVendor == 0x04e8) {
        // found a Samsung device, good
        int idx = -1;
        if ((idx = in_list(dev->descriptor.idProduct, ids)) >= 0) { 
          have_idx = idx;
          return dev;
        }
      }
    }
  }

  return NULL;
}

static usb_dev_handle *dev_open(struct usb_device *dev) {
  int res = -1;
  usb_dev_handle *udev;
  int numeps = 0;

  udev = usb_open(dev);
  if (!udev) {
    fprintf(stderr, "%s: failed to open device, exit.\n", progname);
    exit(EXIT_FAILURE);
  }

//  setuid(getuid());

  res = usb_set_configuration(udev, 1);

  usb_claim_interface(udev, 0);
  numeps = dev->config[0].interface[0].altsetting[0].bNumEndpoints;
  if (numeps == 0) {
    fprintf(stderr, "%s: no endpoints, exit.\n", progname);
    exit(EXIT_FAILURE);
  }

  {
    int eplist[] = { 0x2, 0x81, 0x83 };
    int eplength = sizeof(eplist)/sizeof(eplist[0]);
    int *endpoint = eplist;
    int i;
    for (i = 0; i < eplength; i++) {
      res = usb_resetep(udev, *endpoint);
      res = usb_clear_halt(udev, *endpoint);
      endpoint++;
    }
  }

  return udev;
}

static void send_jpeg(FILE *f, usb_dev_handle *udev) {
  fseek(f, 0, SEEK_END);
  int sz = ftell(f);
  fseek(f, 0, SEEK_SET);

  #define URBBUF_MAX 0x20000
  char buf[URBBUF_MAX];

  #define HDR_LEN 12
  char hdr[HDR_LEN] = {0xa5, 0x5a, 0x18, 0x04, 0xff, 0xff, 0xff, 0xff, 0x48, 0x00, 0x00, 0x00};
  *(int *)(hdr+4) = sz;

  memcpy(buf, hdr, HDR_LEN);
  int off = HDR_LEN;

  while(!feof(f)) {
    int nr = fread(buf+off, 1, URBBUF_MAX - off, f);
    if (nr < 0) break;
    // pad
    memset(buf + off + nr, 0, URBBUF_MAX - off - nr);

    // write it out chunk by chunk
    int timeout = 1000;
    int endpoint = 0x2;
    int res = usb_bulk_write(udev, endpoint, buf, URBBUF_MAX, timeout);

    assert(res >= 0);
    off = 0; // no header on subsequent chunks
  }
}

int main(int argc, char *argv[]) {
  if (argc != 2) {
    fprintf(stderr, "Usage: %s <.jpg file>\n", progname);
    return EXIT_FAILURE;
  }

  struct usb_device *dev = find_dev(index);
  if (!dev) {
    fprintf(stderr, "%s: no photo frame device found, exit.\n", progname);
    exit(EXIT_FAILURE);
  }

  if (need_switch) {
    fprintf(stderr, "%s: found %s, trying to switch to custom product mode...\n", 
        ids[have_idx].name, progname);

    usb_dev_handle *udev;

    udev = usb_open(dev);
    if (!udev) {
      fprintf(stderr, "%s: failed to open device, exit.\n", progname);
      exit(EXIT_FAILURE);
    }

    char buf[254];
    memset(buf, 0, 254);

    int res = usb_control_msg(udev, USB_TYPE_STANDARD | USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, 
      0xfe, 0xfe, buf, 0xfe, 1000);
    fprintf(stderr, "%s: usb_control_msg() = %d\n", progname, res);

    usb_close(udev);
    usleep(500000);
  }

  dev = find_dev(index);
  if (!dev || need_switch) {
    fprintf(stderr, "%s: no photo frame device found, exit.\n", progname);
    exit(EXIT_FAILURE);
  }

  fprintf(stderr, "%s: found %s (%d x %d)\n", 
    progname, ids[have_idx].name, ids[have_idx].width, ids[have_idx].height);

  usb_dev_handle *udev = dev_open(dev);

  FILE *f = fopen(argv[1], "rb");
  if (f == NULL) {
    fprintf(stderr, "%s: failed to open file '%s', exit.\n", progname, argv[1]);
    exit(EXIT_FAILURE);
  }
  send_jpeg(f, udev);
  fclose(f);

  while (1) {
    char buf[2];
    int res = usb_control_msg(udev, USB_TYPE_VENDOR | USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, 
      0x0, 0x0, buf, 0x2, 1000);
    fprintf(stderr, "%s: usb_control_msg() = %d\n", progname, res);

    usleep(500000);
  }

  usb_close(udev);

  return EXIT_SUCCESS;
}

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.