Mercurial > hg > minimon
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; +}