diff 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 bac8ed8d6eb9
children
line wrap: on
line diff
--- a/minimon.c	Sat May 14 23:08:11 2011 +0200
+++ b/minimon.c	Sun May 15 17:48:57 2011 +0200
@@ -2,9 +2,15 @@
 #include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <assert.h>
 #include "usb.h"
 
+#include "linux/fb.h"
+
+#include "common.h"
+
 static const char *progname = "minimon";
 
 static int need_switch = 0;
@@ -112,24 +118,21 @@
   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);
-
+static int send_jpg(jpg_buf_t *jpg_buf, usb_dev_handle *udev) {
   #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;
+  *(int *)(hdr+4) = jpg_buf->size;
 
   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;
+  int jpg_off = 0;
+  int jpg_left = jpg_buf->size;
+  while (jpg_left > 0) {
+    int nr = MIN(URBBUF_MAX - off, jpg_left);
+    memcpy(buf+off, &jpg_buf->ptr[jpg_off], nr);
     // pad
     memset(buf + off + nr, 0, URBBUF_MAX - off - nr);
 
@@ -138,75 +141,134 @@
     int endpoint = 0x2;
     int res = usb_bulk_write(udev, endpoint, buf, URBBUF_MAX, timeout);
 
-    assert(res >= 0);
+    if (res < 0) 
+      return 0;
     off = 0; // no header on subsequent chunks
+    jpg_off += nr;
+    jpg_left -= nr;
   }
+  
+  return 1;
 }
 
 int main(int argc, char *argv[]) {
   if (argc != 2) {
-    fprintf(stderr, "Usage: %s <.jpg file>\n", progname);
+    fprintf(stderr, "Usage: %s </dev/fbX>\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);
+  int fd = open(argv[1], O_RDONLY);
+  if (fd < 0) {
+    perror("minimon framebuffer");
+    exit(EXIT_FAILURE);
+  }
+
+  struct fb_fix_screeninfo sif;
+  if (ioctl(fd, FBIOGET_FSCREENINFO, &sif) < 0) {
+    perror("minimon framebuffer info");
+    exit(EXIT_FAILURE);
+  }
+
+  printf("id %s\n", sif.id);
+  printf("type %d, aux %d\n", sif.type, sif.type_aux);
+  printf("visual %d\n", sif.visual);
+  printf("accel %d\n", sif.accel);
+  printf("line length %d\n", sif.line_length);
+  printf("mem %d\n", sif.smem_len);
+
+  struct fb_var_screeninfo siv;
+  if (ioctl(fd, FBIOGET_VSCREENINFO, &siv) < 0) {
+    perror("minimon framebuffer info");
+    exit(EXIT_FAILURE);
+  }
+
+  printf("res x %d y %d\n", siv.xres, siv.yres);
+  printf("bpp %d\n", siv.bits_per_pixel);
+
+  size_t fb_mem_size = siv.xres * siv.yres * siv.bits_per_pixel / 8;
+  void *fb_mem = mmap(NULL, fb_mem_size, PROT_READ, MAP_SHARED, fd, 0);
+  if (fb_mem == MAP_FAILED) {
+    perror("minimon framebuffer mapping");
     exit(EXIT_FAILURE);
   }
 
-  if (need_switch) {
-    fprintf(stderr, "%s: found %s, trying to switch to custom product mode...\n", 
+  while (1) {
+    struct usb_device *dev = find_dev(index);
+    if (!dev) {
+      fprintf(stderr, "%s: no photo frame device found, suspending...\n", progname);
+      sleep(1);
+      continue;
+    }
+
+    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;
+      usb_dev_handle *udev;
+      udev = usb_open(dev);
+      if (!udev) {
+        fprintf(stderr, "%s: failed to open device, exit.\n", progname);
+        exit(EXIT_FAILURE);
+      }
 
-    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, 
+        0x06, 0xfe, 0xfe, buf, 0xfe, 1000);
+      fprintf(stderr, "%s: usb_control_msg() = %d\n", progname, res);
+      usb_close(udev);
+      sleep(1);
+    }
+
+    dev = find_dev(index);
+    if (!dev || need_switch) {
+      fprintf(stderr, "%s: no photo frame device found, suspending...\n", progname);
+      sleep(1);
+      continue;
     }
 
-    char buf[254];
-    memset(buf, 0, 254);
+    int mon_width = ids[have_idx].width;
+    int mon_height = ids[have_idx].height;
+    fprintf(stderr, "%s: found %s (%d x %d)\n", 
+      progname, ids[have_idx].name, mon_width, mon_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, 0xfe, buf, 0xfe, 1000);
-    fprintf(stderr, "%s: usb_control_msg() = %d\n", progname, res);
+    while (1) {
+      int transfer = 1;
+      
+      // poll status to avoid going back to photoframe mode
+      char buf[2];
+      int res = usb_control_msg(udev, USB_TYPE_VENDOR | USB_ENDPOINT_IN, 
+        0x06, 0x0, 0x0, buf, 0x2, 1000);
+      if (res != 2) {
+        break;
+      }
+      else if (buf[0] != 0) {
+        transfer = 0;
+      }
+
+      if (transfer) {
+        fprintf(stderr, ".");
+        jpg_buf_t jpg_buf = build_jpg_from_fb((unsigned char *)fb_mem, siv.xres, siv.yres, siv.bits_per_pixel, mon_width, mon_height);
+
+        if (!send_jpg(&jpg_buf, udev)) {
+          free(jpg_buf.ptr);
+          break;
+        }
+        free(jpg_buf.ptr);
+      }
+      else 
+        fprintf(stderr, "o");
+
+      usleep(500000);
+    }
 
     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);
+  munmap(fb_mem, fb_mem_size);
+  close(fd);
 
   return EXIT_SUCCESS;
 }

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