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