changeset 1:111d4bbce605

improving
author Peter Meerwald <pmeerw@pmeerw.net>
date Sat, 07 May 2011 19:00:43 +0200
parents 71b9540bdd23
children bac8ed8d6eb9
files Makefile README.txt frame-ctrl.py minimon.c test-1024x600.jpg
diffstat 5 files changed, 206 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Sat May 07 19:00:43 2011 +0200
@@ -0,0 +1,10 @@
+all: minimon
+
+minimon: minimon.c
+	$(CC) $(CFLAGS) -Wall -g -o $@ minimon.c -lusb
+	
+clean:
+	rm -f minimon
+	
+install:
+	
--- a/README.txt	Sat May 07 17:29:58 2011 +0200
+++ b/README.txt	Sat May 07 19:00:43 2011 +0200
@@ -1,2 +1,5 @@
 
 based on Grace Woo's work: http://web.media.mit.edu/~gracewoo/stuff/picframe/
+
+and using ideas from https://github.com/Gekkio/samsung-photo-frame-ctrl
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frame-ctrl.py	Sat May 07 19:00:43 2011 +0200
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+import os
+import struct
+import sys
+import time
+import usb.core
+from usb.util import *
+
+vendorId = 0x04e8
+models = {'SPF-87H': (0x2033, 0x2034), 'SPF-107H': (0x2027, 0x2028) }
+
+chunkSize = 0x4000
+bufferSize = 0x20000
+
+def expect(result, verifyList):
+  resultList = result.tolist()
+  if resultList != verifyList:
+    print >> sys.stderr, "Warning: Expected " + str(verifyList) + " but got " + str(resultList)
+
+def storageToDisplay(dev):
+  print "Setting device to display mode"
+  try:
+    dev.ctrl_transfer(CTRL_TYPE_STANDARD | CTRL_IN | CTRL_RECIPIENT_DEVICE, 0x06, 0xfe, 0xfe, 254)
+  except usb.core.USBError as e:
+    errorStr = str(e)
+    if errorStr != 'No such device (it may have been disconnected)':
+      raise e
+
+def displayModeSetup(dev):
+  print "Sending setup commands to device"
+  result = dev.ctrl_transfer(CTRL_TYPE_VENDOR | CTRL_IN | CTRL_RECIPIENT_DEVICE, 0x04, 0x00, 0x00, 1)
+  expect(result, [ 0x03 ])
+#  result = dev.ctrl_transfer(CTRL_TYPE_VENDOR | CTRL_IN | CTRL_RECIPIENT_DEVICE, 0x01, 0x00, 0x00, 2)
+#  expect(result, [ 0x09, 0x04 ])
+#  result = dev.ctrl_transfer(CTRL_TYPE_VENDOR | CTRL_IN | CTRL_RECIPIENT_DEVICE, 0x02, 0x00, 0x00, 1)
+#  expect(result, [ 0x46 ])
+
+def paddedBytes(buf, size):
+  diff = size - len(buf)
+  return buf + bytes(b'\x00') * diff
+
+def chunkyWrite(dev, buf):
+  pos = 0
+  while pos < bufferSize:
+    dev.write(0x02, buf[pos:pos+chunkSize])
+    pos += chunkSize
+
+def writeImage(dev):
+#  result = dev.ctrl_transfer(CTRL_TYPE_STANDARD | CTRL_IN | CTRL_RECIPIENT_DEVICE, 0x06, 0x0300, 0x00, 255)
+#  expect(result, [ 0x04, 0x03, 0x09, 0x04 ])
+
+#  result = dev.ctrl_transfer(CTRL_TYPE_STANDARD | CTRL_IN | CTRL_RECIPIENT_DEVICE, 0x06, 0x0301, 0x0409, 255)
+
+  if len(sys.argv) < 2 or sys.argv[1] == "-":
+    content = sys.stdin.read()
+  else:
+    f = open(sys.argv[1])
+    content = f.read()
+    f.close()
+
+  size = struct.pack('I', len(content))
+  header = b'\xa5\x5a\x09\x04' + size + b'\x46\x00\x00\x00'
+
+  content = header + content
+
+  pos = 0
+  while pos < len(content):
+    buf = paddedBytes(content[pos:pos+bufferSize], bufferSize)
+    chunkyWrite(dev, buf)
+    pos += bufferSize
+
+  
+#  result = dev.ctrl_transfer(CTRL_TYPE_VENDOR | CTRL_IN | CTRL_RECIPIENT_DEVICE, 0x06, 0x00, 0x00, 2)
+#  expect(result, [ 0x00, 0x00 ])
+
+found = False
+
+for k, v in models.iteritems():
+  dev = usb.core.find(idVendor=vendorId, idProduct=v[0])
+  if dev:
+    print "Found " + k + " in storage mode"
+    storageToDisplay(dev)
+    time.sleep(1)
+    dev = usb.core.find(idVendor=vendorId, idProduct=v[1])
+    displayModeSetup(dev)
+    found = True
+  if not dev:
+    dev = usb.core.find(idVendor=vendorId, idProduct=v[1])
+  if dev:
+    print "Found " + k + " in display mode"
+    dev.set_configuration()
+    writeImage(dev)
+    found = True
+
+if not found:
+  print >> sys.stderr, "No supported devices found"
+  sys.exit(-1)
--- a/minimon.c	Sat May 07 17:29:58 2011 +0200
+++ b/minimon.c	Sat May 07 19:00:43 2011 +0200
@@ -7,7 +7,50 @@
 
 static const char *progname = "minimon";
 
-struct usb_device *find_dev() {
+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;
+
+static id_info_t ids[] = {
+  {0x2027, 0x2028, },
+  {0xffff, 0xffff, "SPF-75H", 800, 480}, 
+  {0xffff, 0xffff, "SPF-83H", 800, 600}, // 85P??
+  {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;
 
@@ -17,9 +60,13 @@
 
   for (bus = usb_busses; bus; bus = bus->next) {
     for (dev = bus->devices; dev; dev = dev->next) {
-      if (dev->descriptor.idVendor == 0x04e8 &&
-          dev->descriptor.idProduct == 0x2028) {
-            return dev;
+      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;
+        }
       }
     }
   }
@@ -27,7 +74,7 @@
   return NULL;
 }
 
-usb_dev_handle *dev_open(struct usb_device *dev) {
+static usb_dev_handle *dev_open(struct usb_device *dev) {
   int res = -1;
   char buf[256];
   usb_dev_handle *udev;
@@ -52,14 +99,14 @@
 
   strcpy(buf, "** no string **");
   res = usb_get_string_simple(udev, dev->descriptor.iManufacturer, buf, sizeof(buf));
-  fprintf(stderr, "usb_get_string_simple => %d, %s\n", res, buf);
+  // fprintf(stderr, "usb_get_string_simple => %d, %s\n", res, buf);
 
   {
     int eplist[] = { 0x2, 0x81, 0x83 };
     int eplength = sizeof(eplist)/sizeof(eplist[0]);
     int *endpoint = eplist;
     int i;
-    for (i=0; i<eplength; i++) {
+    for (i = 0; i < eplength; i++) {
       res = usb_resetep(udev, *endpoint);
       res = usb_clear_halt(udev, *endpoint);
       endpoint++;
@@ -69,8 +116,7 @@
   return udev;
 }
 
-
-void send_jpeg(FILE *f, usb_dev_handle *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);
@@ -103,15 +149,53 @@
 
 int main(int argc, char *argv[]) {
   if (argc != 2) {
-    fprintf(stderr, "Usage: %s FILE", progname);
+    fprintf(stderr, "Usage: %s <.jpg file>\n", progname);
     return EXIT_FAILURE;
   }
 
   struct usb_device *dev = find_dev(index);
-  assert(dev != NULL);
+  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);
+  }
+
+  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);
 
+//  int res = usb_control_msg(udev, USB_TYPE_STANDARD | USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, 
+//      0xfe, 0x0, buf, 0x0, 1000);
+//  fprintf(stderr, "%s: usb_control_msg() = %d\n", progname, res);
+
   FILE *f = fopen(argv[1], "rb");
   if (f == NULL) {
     fprintf(stderr, "%s: failed to open file '%s', exit.\n", progname, argv[1]);
Binary file test-1024x600.jpg has changed

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