diff disp-minimon.c @ 10:078dc69945ad

working: libjpeg-turbo support, handle fb and monitor with different size
author Peter Meerwald <pmeerw@pmeerw.net>
date Sun, 15 May 2011 17:48:57 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/disp-minimon.c	Sun May 15 17:48:57 2011 +0200
@@ -0,0 +1,212 @@
+#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.