# HG changeset patch # User Peter Meerwald # Date 1304787643 -7200 # Node ID 111d4bbce6050796d5329666cd5d21b347764f56 # Parent 71b9540bdd23a9620233558fd29454c7ab241cfa improving diff -r 71b9540bdd23 -r 111d4bbce605 Makefile --- /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: + diff -r 71b9540bdd23 -r 111d4bbce605 README.txt --- 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 + diff -r 71b9540bdd23 -r 111d4bbce605 frame-ctrl.py --- /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) diff -r 71b9540bdd23 -r 111d4bbce605 minimon.c --- 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\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]); diff -r 71b9540bdd23 -r 111d4bbce605 test-1024x600.jpg Binary file test-1024x600.jpg has changed