changeset 2:bac8ed8d6eb9

add jpeg coding and test stuff
author Peter Meerwald <pmeerw@pmeerw.net>
date Sun, 08 May 2011 18:22:22 +0200
parents 111d4bbce605
children e8957085fe8a
files Makefile fb.c fbt.c frame-ctrl.py jpg.c minimon.c plug-mass_log.txt to-mass_log.txt to-mini_log.txt vfb/Makefile vfb/vfb.c
diffstat 10 files changed, 990 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sat May 07 19:00:43 2011 +0200
+++ b/Makefile	Sun May 08 18:22:22 2011 +0200
@@ -1,7 +1,10 @@
-all: minimon
+all: minimon fbt
 
-minimon: minimon.c
-	$(CC) $(CFLAGS) -Wall -g -o $@ minimon.c -lusb
+minimon: minimon.c jpg.c
+	$(CC) $(CFLAGS) -Wall -g -o $@ minimon.c jpg.c fb.c -lusb -ljpeg
+
+fbt: fbt.c
+	$(CC) $(CFLAGS) -Wall -g -o $@ fbt.c 
 	
 clean:
 	rm -f minimon
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbt.c	Sun May 08 18:22:22 2011 +0200
@@ -0,0 +1,38 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "linux/fb.h"
+
+int main(int argc, char *argv[]) {
+
+  int fd = open("/dev/fb0", O_RDWR);
+  if (fd < 0) {
+    perror("");
+    exit(EXIT_FAILURE);
+  }
+  
+  struct fb_fix_screeninfo sif;
+  if (ioctl(fd, FBIOGET_VSCREENINFO, &sif) < 0) {
+    perror("");
+    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);
+
+  struct fb_var_screeninfo siv;
+  if (ioctl(fd, FBIOGET_VSCREENINFO, &siv) < 0) {
+    perror("");
+    exit(EXIT_FAILURE);
+  }
+
+  printf("res x %d y %d\n", siv.xres, siv.yres);
+  printf("bpp %d\n", siv.bits_per_pixel);
+
+  exit(EXIT_SUCCESS);
+}
--- a/frame-ctrl.py	Sat May 07 19:00:43 2011 +0200
+++ b/frame-ctrl.py	Sun May 08 18:22:22 2011 +0200
@@ -8,7 +8,10 @@
 from usb.util import *
 
 vendorId = 0x04e8
-models = {'SPF-87H': (0x2033, 0x2034), 'SPF-107H': (0x2027, 0x2028) }
+models = {'SPF-87H': (0x2033, 0x2034), 
+  'SPF-107H': (0x2027, 0x2028),
+  'SPF-107H': (0x2035, 0x2036),
+   }
 
 chunkSize = 0x4000
 bufferSize = 0x20000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jpg.c	Sun May 08 18:22:22 2011 +0200
@@ -0,0 +1,124 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "jpeglib.h"
+#include "jerror.h"
+
+typedef struct {
+  struct jpeg_destination_mgr pub; /* public fields */
+
+  unsigned char ** outbuffer;	/* target buffer */
+  unsigned long * outsize;
+  unsigned char * newbuffer;	/* newly allocated buffer */
+  JOCTET * buffer;		/* start of buffer */
+  size_t bufsize;
+} mem_dest_mgr;
+
+typedef mem_dest_mgr * mem_dest_mgr_ptr;
+
+void init_mem_destination (j_compress_ptr cinfo) {
+}
+
+boolean empty_mem_output_buffer(j_compress_ptr cinfo) {
+  size_t nextsize;
+  JOCTET * nextbuffer;
+  mem_dest_mgr_ptr dest = (mem_dest_mgr_ptr) cinfo->dest;
+
+  /* Try to allocate new buffer with double size */
+  nextsize = dest->bufsize * 2;
+  nextbuffer = malloc(nextsize);
+
+  if (nextbuffer == NULL)
+    ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
+
+  memcpy(nextbuffer, dest->buffer, dest->bufsize);
+
+  if (dest->newbuffer != NULL)
+    free(dest->newbuffer);
+
+  dest->newbuffer = nextbuffer;
+
+  dest->pub.next_output_byte = nextbuffer + dest->bufsize;
+  dest->pub.free_in_buffer = dest->bufsize;
+
+  dest->buffer = nextbuffer;
+  dest->bufsize = nextsize;
+
+  return TRUE;
+}
+
+void term_mem_destination(j_compress_ptr cinfo) {
+  mem_dest_mgr_ptr dest = (mem_dest_mgr_ptr) cinfo->dest;
+
+  *dest->outbuffer = dest->buffer;
+  *dest->outsize = dest->bufsize - dest->pub.free_in_buffer;
+}
+
+void jpeg_mem_dest(j_compress_ptr cinfo, unsigned char ** outbuffer, unsigned long * outsize) {
+  mem_dest_mgr_ptr dest;
+
+  if (outbuffer == NULL || outsize == NULL)	/* sanity check */
+    ERREXIT(cinfo, JERR_BUFFER_SIZE);
+
+  /* The destination object is made permanent so that multiple JPEG images
+   * can be written to the same buffer without re-executing jpeg_mem_dest.
+   */
+  if (cinfo->dest == NULL) {	/* first time for this JPEG object? */
+    cinfo->dest = (struct jpeg_destination_mgr *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+				  sizeof(mem_dest_mgr));
+  }
+
+  dest = (mem_dest_mgr_ptr) cinfo->dest;
+  dest->pub.init_destination = init_mem_destination;
+  dest->pub.empty_output_buffer = empty_mem_output_buffer;
+  dest->pub.term_destination = term_mem_destination;
+  dest->outbuffer = outbuffer;
+  dest->outsize = outsize;
+  dest->newbuffer = NULL;
+
+  if (*outbuffer == NULL || *outsize == 0) {
+    /* Allocate initial buffer */
+    dest->newbuffer = *outbuffer = malloc(65536);
+    if (dest->newbuffer == NULL)
+      ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
+    *outsize = 65536;
+  }
+
+  dest->pub.next_output_byte = dest->buffer = *outbuffer;
+  dest->pub.free_in_buffer = dest->bufsize = *outsize;
+}
+
+
+int build_jpg(JSAMPLE *image_buf, int width, int height) {
+  int scanline;
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  
+  cinfo.err = jpeg_std_error(&jerr);
+  jpeg_create_compress(&cinfo);
+
+  unsigned long out_size = 1<<20;
+  unsigned char *out_buf = NULL;
+  jpeg_mem_dest(&cinfo, &out_buf, &out_size);
+
+  cinfo.image_width = width;
+  cinfo.image_height = height;
+  cinfo.input_components = 3;
+  cinfo.in_color_space = JCS_RGB;
+  jpeg_set_defaults(&cinfo);
+
+  jpeg_start_compress(&cinfo, TRUE);
+
+  for (scanline = 0; scanline < height; scanline++) {
+    JSAMPROW *row_ptr;
+    row_ptr = &image_buf[scanline * width];
+    jpeg_write_scanlines(&cinfo, row_ptr, 1);
+  }
+
+  jpeg_finish_compress(&cinfo);
+
+  jpeg_destroy_compress(&cinfo);
+
+  return 0;
+}
--- a/minimon.c	Sat May 07 19:00:43 2011 +0200
+++ b/minimon.c	Sun May 08 18:22:22 2011 +0200
@@ -18,10 +18,11 @@
   int height;
 } id_info_t;
 
+// there are many more, 
 static id_info_t ids[] = {
-  {0x2027, 0x2028, },
+  {0x2027, 0x2028, "SPF-107H", 1024, 600},
   {0xffff, 0xffff, "SPF-75H", 800, 480}, 
-  {0xffff, 0xffff, "SPF-83H", 800, 600}, // 85P??
+  {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},  
@@ -76,7 +77,6 @@
 
 static usb_dev_handle *dev_open(struct usb_device *dev) {
   int res = -1;
-  char buf[256];
   usb_dev_handle *udev;
   int numeps = 0;
 
@@ -86,7 +86,7 @@
     exit(EXIT_FAILURE);
   }
 
-  setuid(getuid());
+//  setuid(getuid());
 
   res = usb_set_configuration(udev, 1);
 
@@ -97,10 +97,6 @@
     exit(EXIT_FAILURE);
   }
 
-  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);
-
   {
     int eplist[] = { 0x2, 0x81, 0x83 };
     int eplength = sizeof(eplist)/sizeof(eplist[0]);
@@ -179,6 +175,7 @@
     fprintf(stderr, "%s: usb_control_msg() = %d\n", progname, res);
 
     usb_close(udev);
+    usleep(500000);
   }
 
   dev = find_dev(index);
@@ -192,10 +189,6 @@
 
   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]);
@@ -204,5 +197,16 @@
   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;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plug-mass_log.txt	Sun May 08 18:22:22 2011 +0200
@@ -0,0 +1,67 @@
+ef67cb00 2793832298 S Ci:1:018:0 s 80 06 0100 0000 0012 18 <
+ef67cb00 2793832615 C Ci:1:018:0 0 18 = 12010002 00000040 e8043520 00020102 0301
+deda9c80 2793832774 S Ci:1:018:0 s 80 06 0200 0000 0009 9 <
+deda9c80 2793832985 C Ci:1:018:0 0 9 = 09022700 010100c0 32
+deda9c80 2793833055 S Ci:1:018:0 s 80 06 0200 0000 0027 39 <
+deda9c80 2793833359 C Ci:1:018:0 0 39 = 09022700 010100c0 32090400 00030806 50000705 81020002 00070502 02000200
+ede01780 2794401395 S Ci:1:018:0 s 80 06 0100 0000 0040 64 <
+ede01780 2794401603 C Ci:1:018:0 0 18 = 12010002 00000040 e8043520 00020102 0301
+ede01100 2794632908 S Ci:1:018:0 s 80 06 0100 0000 0012 18 <
+ede01100 2794633102 C Ci:1:018:0 0 18 = 12010002 00000040 e8043520 00020102 0301
+ede01100 2794637808 S Ci:1:018:0 s 80 06 0200 0000 0009 9 <
+ede01100 2794638105 C Ci:1:018:0 0 9 = 09022700 010100c0 32
+ede01780 2794654838 S Ci:1:018:0 s 80 06 0300 0000 00ff 255 <
+ede01780 2794655104 C Ci:1:018:0 0 4 = 04030904
+ede01780 2794658803 S Ci:1:018:0 s 80 06 0303 0409 00ff 255 <
+ede01780 2794658978 C Ci:1:018:0 0 14 = 0e034900 52003100 30000000 0000
+ede01780 2794663340 S Ci:1:018:0 s 80 06 0200 0000 00ff 255 <
+ede01780 2794663604 C Ci:1:018:0 0 39 = 09022700 010100c0 32090400 00030806 50000705 81020002 00070502 02000200
+ede01780 2794671490 S Ci:1:018:0 s 80 06 0300 0000 00ff 255 <
+ede01780 2794671736 C Ci:1:018:0 0 4 = 04030904
+ede01780 2794678269 S Ci:1:018:0 s 80 06 0302 0409 00ff 255 <
+ede01780 2794678476 C Ci:1:018:0 0 56 = 38035300 41004d00 53005500 4e004700 20004400 69006700 69007400 61006c00
+ede01780 2794685397 S Ci:1:018:0 s 80 06 0300 0000 00ff 255 <
+ede01780 2794685607 C Ci:1:018:0 0 4 = 04030904
+ede01780 2794693354 S Ci:1:018:0 s 80 06 0302 0409 00ff 255 <
+ede01780 2794693606 C Ci:1:018:0 0 56 = 38035300 41004d00 53005500 4e004700 20004400 69006700 69007400 61006c00
+ede6a580 2794755583 S Ci:1:018:0 s 80 06 0100 0000 0012 18 <
+ede6a580 2794755854 C Ci:1:018:0 0 18 = 12010002 00000040 e8043520 00020102 0301
+ede6a580 2794759604 S Ci:1:018:0 s 80 06 0200 0000 0009 9 <
+ede6a580 2794759853 C Ci:1:018:0 0 9 = 09022700 010100c0 32
+ede6a580 2794764735 S Ci:1:018:0 s 80 06 0200 0000 0027 39 <
+ede6a580 2794764980 C Ci:1:018:0 0 39 = 09022700 010100c0 32090400 00030806 50000705 81020002 00070502 02000200
+edf32180 2794769569 S Ci:1:018:0 s 80 06 0300 0000 0002 2 <
+edf32180 2794769865 C Ci:1:018:0 0 2 = 0403
+edf32180 2794776538 S Ci:1:018:0 s 80 06 0300 0000 0004 4 <
+edf32180 2794776730 C Ci:1:018:0 0 4 = 04030904
+ede6a580 2794783402 S Ci:1:018:0 s 80 06 0303 0409 0002 2 <
+ede6a580 2794783599 C Ci:1:018:0 0 2 = 0e03
+edf32180 2794791041 S Ci:1:018:0 s 80 06 0303 0409 000e 14 <
+edf32180 2794791238 C Ci:1:018:0 0 14 = 0e034900 52003100 30000000 0000
+edf32180 2794956855 S Ci:1:018:0 s a1 fe 0000 0000 0001 1 <
+edf32180 2794957107 C Ci:1:018:0 0 1 = 01
+edf32180 2794998006 S Co:1:018:0 s 02 01 0000 0081 0000 0
+edf32180 2794998235 C Co:1:018:0 0 0
+dee8c000 2795024479 S Co:1:018:0 s 02 01 0000 0081 0000 0
+dee8c000 2795024731 C Co:1:018:0 0 0
+dee8c000 2795055506 S Co:1:018:0 s 02 01 0000 0081 0000 0
+dee8c000 2795055729 C Co:1:018:0 0 0
+e358db80 2795214780 S Co:1:018:0 s 02 01 0000 0081 0000 0
+e358db80 2795215117 C Co:1:018:0 0 0
+e358db80 2795236568 S Co:1:018:0 s 02 01 0000 0081 0000 0
+e358db80 2795236856 C Co:1:018:0 0 0
+e358db80 2795282524 S Co:1:018:0 s 02 01 0000 0081 0000 0
+e358db80 2795282864 C Co:1:018:0 0 0
+e358db80 2795304456 S Co:1:018:0 s 02 01 0000 0081 0000 0
+e358db80 2795304728 C Co:1:018:0 0 0
+e358d100 2795494769 S Ci:1:018:0 s 80 06 00fe 00fe 00ff 255 <
+e358d100 2795499103 C Ci:1:018:0 0 8 = 00000001 a8019100
+e358d100 2795511395 S Ci:1:018:0 s 80 06 00fe 00fe 00e0 224 <
+e358d100 2795511604 C Ci:1:018:0 0 0
+def69480 2795635976 S Ci:1:018:0 s 80 06 00fe 00fe 00fb 251 <
+def69480 2795797513 C Ci:1:018:0 0 0
+e358dd00 2797809223 S Co:1:018:0 s 02 01 0000 0081 0000 0
+e358dd00 2797809494 C Co:1:018:0 0 0
+d4bd8e80 2797926292 S Co:1:018:0 s 02 01 0000 0081 0000 0
+d4bd8e80 2797926612 C Co:1:018:0 0 0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/to-mass_log.txt	Sun May 08 18:22:22 2011 +0200
@@ -0,0 +1,65 @@
+ef4c5e80 892738751 S Ci:1:014:0 s c0 06 0000 0000 0002 2 <
+ef4c5e80 892738989 C Ci:1:014:0 0 2 = 0000
+ef4c5880 893263743 S Ci:1:014:0 s c0 06 0000 0000 0002 2 <
+ef4c5880 893263990 C Ci:1:014:0 0 2 = 0000
+f0946200 893799754 S Ci:1:014:0 s c0 06 0000 0000 0002 2 <
+f0946200 893799995 C Ci:1:014:0 0 2 = 0000
+def03200 894296627 S Ci:1:014:0 s c0 06 0000 0000 0002 2 <
+def03200 894297004 C Ci:1:014:0 0 2 = 0000
+def03b80 894822781 S Ci:1:014:0 s c0 06 0000 0000 0002 2 <
+def03b80 894822991 C Ci:1:014:0 0 2 = 0000
+ef515a80 895344445 S Co:1:014:0 s 40 05 0000 0000 0004 4 = a3394200
+ef515380 895344825 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+ef515380 895344839 C Ci:1:001:0 0 4 = 00010100
+ef515380 895344860 S Co:1:001:0 s 23 01 0010 0001 0000 0
+ef515380 895344868 C Co:1:001:0 0 0
+ef515a80 895345238 C Co:1:014:0 -108 4 >
+ef515380 895345702 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+ef515380 895345713 C Ci:1:001:0 0 4 = 00010000
+edd94200 895374748 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+edd94200 895374764 C Ci:1:001:0 0 4 = 01050100
+edd94200 895374773 S Co:1:001:0 s 23 01 0010 0001 0000 0
+edd94200 895374781 C Co:1:001:0 0 0
+ef499780 895407629 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+ef499780 895407752 C Ci:1:001:0 0 4 = 01050000
+ef499780 895439749 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+ef499780 895439769 C Ci:1:001:0 0 4 = 01050000
+ef499780 895471727 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+ef499780 895471744 C Ci:1:001:0 0 4 = 01050000
+ef499d80 895503720 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+ef499d80 895503737 C Ci:1:001:0 0 4 = 01050000
+ef499d80 895503762 S Co:1:001:0 s 23 03 0004 0001 0000 0
+ef499d80 895503770 C Co:1:001:0 0 0
+ef499d80 895559772 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+ef499d80 895560045 C Ci:1:001:0 0 4 = 03051000
+ef499d80 895615722 S Co:1:001:0 s 23 01 0014 0001 0000 0
+ef499d80 895615739 C Co:1:001:0 0 0
+ef499d80 895615770 S Ci:1:000:0 s 80 06 0100 0000 0040 64 <
+ef499d80 895615987 C Ci:1:000:0 0 18 = 12010002 00000040 e8043520 00020102 0301
+ef499d80 895616046 S Co:1:001:0 s 23 03 0004 0001 0000 0
+ef499d80 895616059 C Co:1:001:0 0 0
+edf32b00 895671760 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+edf32b00 895672100 C Ci:1:001:0 0 4 = 03051000
+edf32b00 895727746 S Co:1:001:0 s 23 01 0014 0001 0000 0
+edf32b00 895727766 C Co:1:001:0 0 0
+edf32b00 895727777 S Co:1:000:0 s 00 05 000f 0000 0000 0
+edf32b00 895727989 C Co:1:000:0 0 0
+edf32b00 895747746 S Ci:1:015:0 s 80 06 0100 0000 0012 18 <
+edf32b00 895747987 C Ci:1:015:0 0 18 = 12010002 00000040 e8043520 00020102 0301
+eea43880 895748035 S Ci:1:015:0 s 80 06 0200 0000 0009 9 <
+eea43880 895748239 C Ci:1:015:0 0 9 = 09022700 010100c0 32
+eea43880 895748311 S Ci:1:015:0 s 80 06 0200 0000 0027 39 <
+eea43880 895748483 C Ci:1:015:0 0 39 = 09022700 010100c0 32090400 00030806 50000705 81020002 00070502 02000200
+eea43880 895748524 S Ci:1:015:0 s 80 06 0300 0000 00ff 255 <
+eea43880 895748732 C Ci:1:015:0 0 4 = 04030904
+eea43880 895748757 S Ci:1:015:0 s 80 06 0302 0409 00ff 255 <
+eea43880 895748987 C Ci:1:015:0 0 56 = 38035300 41004d00 53005500 4e004700 20004400 69006700 69007400 61006c00
+eea43880 895749065 S Ci:1:015:0 s 80 06 0301 0409 00ff 255 <
+eea43880 895749233 C Ci:1:015:0 0 22 = 16035300 41004d00 53005500 4e004700 00000000 0000
+eea43880 895749274 S Ci:1:015:0 s 80 06 0303 0409 00ff 255 <
+eea43880 895749487 C Ci:1:015:0 0 14 = 0e034900 52003100 30000000 0000
+eea43880 895749838 S Co:1:015:0 s 00 09 0001 0000 0000 0
+eea43880 895750113 C Co:1:015:0 0 0
+ede01c00 895771384 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+ede01c00 895771406 C Ci:1:001:0 0 4 = 03050000
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/to-mini_log.txt	Sun May 08 18:22:22 2011 +0200
@@ -0,0 +1,55 @@
+f69d0a00 1137091779 S Ci:1:015:0 s 80 06 00fe 00fe 00fe 254 <
+edc41c00 1137092082 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+edc41c00 1137092093 C Ci:1:001:0 0 4 = 00010100
+edc41c00 1137092106 S Co:1:001:0 s 23 01 0010 0001 0000 0
+edc41c00 1137092116 C Co:1:001:0 0 0
+f69d0a00 1137092773 C Ci:1:015:0 -108 0
+edc41800 1137098970 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+edc41800 1137099000 C Ci:1:001:0 0 4 = 00010000
+e24f9780 1137131957 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+e24f9780 1137131979 C Ci:1:001:0 0 4 = 01050100
+e24f9780 1137131989 S Co:1:001:0 s 23 01 0010 0001 0000 0
+e24f9780 1137131995 C Co:1:001:0 0 0
+dac9b300 1137163733 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+dac9b300 1137163753 C Ci:1:001:0 0 4 = 01050000
+dac9b300 1137195730 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+dac9b300 1137195751 C Ci:1:001:0 0 4 = 01050000
+dac9b300 1137227738 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+dac9b300 1137227758 C Ci:1:001:0 0 4 = 01050000
+dac9b300 1137259745 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+dac9b300 1137259764 C Ci:1:001:0 0 4 = 01050000
+dac9b300 1137259787 S Co:1:001:0 s 23 03 0004 0001 0000 0
+dac9b300 1137259795 C Co:1:001:0 0 0
+dec36180 1137315746 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+dec36180 1137316006 C Ci:1:001:0 0 4 = 03051000
+dec36180 1137372621 S Co:1:001:0 s 23 01 0014 0001 0000 0
+dec36180 1137372640 C Co:1:001:0 0 0
+dec36180 1137372673 S Ci:1:000:0 s 80 06 0100 0000 0040 64 <
+dec36180 1137372893 C Ci:1:000:0 0 18 = 12010002 ff000040 e8043620 00020102 0301
+dec36180 1137373084 S Co:1:001:0 s 23 03 0004 0001 0000 0
+dec36180 1137373096 C Co:1:001:0 0 0
+dec36300 1137428918 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+dec36300 1137429143 C Ci:1:001:0 0 4 = 03051000
+eddfc800 1137486733 S Co:1:001:0 s 23 01 0014 0001 0000 0
+eddfc800 1137486752 C Co:1:001:0 0 0
+eddfc800 1137486765 S Co:1:000:0 s 00 05 0010 0000 0000 0
+eddfc800 1137487018 C Co:1:000:0 0 0
+eddfce80 1137506794 S Ci:1:016:0 s 80 06 0100 0000 0012 18 <
+eddfce80 1137507017 C Ci:1:016:0 0 18 = 12010002 ff000040 e8043620 00020102 0301
+eddfce80 1137507065 S Ci:1:016:0 s 80 06 0200 0000 0009 9 <
+eddfce80 1137507263 C Ci:1:016:0 0 9 = 09022700 010100c0 32
+eddfce80 1137507309 S Ci:1:016:0 s 80 06 0200 0000 0027 39 <
+eddfce80 1137507515 C Ci:1:016:0 0 39 = 09022700 010100c0 32090400 0003ffff ff000705 81020002 00070502 02000200
+eddfce80 1137507558 S Ci:1:016:0 s 80 06 0300 0000 00ff 255 <
+eddfce80 1137507765 C Ci:1:016:0 0 4 = 04030904
+eddfce80 1137507816 S Ci:1:016:0 s 80 06 0302 0409 00ff 255 <
+eddfce80 1137508015 C Ci:1:016:0 0 56 = 38035300 41004d00 53005500 4e004700 20004400 69006700 69007400 61006c00
+eddfce80 1137508049 S Ci:1:016:0 s 80 06 0301 0409 00ff 255 <
+eddfce80 1137508263 C Ci:1:016:0 0 22 = 16035300 41004d00 53005500 4e004700 00000000 0000
+eddfce80 1137508298 S Ci:1:016:0 s 80 06 0303 0409 00ff 255 <
+eddfce80 1137508512 C Ci:1:016:0 0 14 = 0e034900 52003100 30000000 0000
+eddfce80 1137508872 S Co:1:016:0 s 00 09 0001 0000 0000 0
+eddfce80 1137509142 C Co:1:016:0 0 0
+eddfce80 1137509511 S Ci:1:001:0 s a3 00 0000 0001 0004 4 <
+eddfce80 1137509526 C Ci:1:001:0 0 4 = 03050000
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vfb/Makefile	Sun May 08 18:22:22 2011 +0200
@@ -0,0 +1,5 @@
+obj-m := vfb.o
+KDIR := /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+default:
+	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vfb/vfb.c	Sun May 08 18:22:22 2011 +0200
@@ -0,0 +1,610 @@
+/*
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
+ *
+ *      Copyright (C) 2002 James Simmons
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <linux/fb.h>
+#include <linux/init.h>
+
+    /*
+     *  RAM we reserve for the frame buffer. This defines the maximum screen
+     *  size
+     *
+     *  The default can be overridden if the driver is compiled as a module
+     */
+
+#define VIDEOMEMSIZE	(1*1024*1024)	/* 1 MB */
+
+static void *videomemory;
+static u_long videomemorysize = VIDEOMEMSIZE;
+module_param(videomemorysize, ulong, 0);
+
+/**********************************************************************
+ *
+ * Memory management
+ *
+ **********************************************************************/
+static void *rvmalloc(unsigned long size)
+{
+	void *mem;
+	unsigned long adr;
+
+	size = PAGE_ALIGN(size);
+	mem = vmalloc_32(size);
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		SetPageReserved(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	return mem;
+}
+
+static void rvfree(void *mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (!mem)
+		return;
+
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		ClearPageReserved(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	vfree(mem);
+}
+
+static struct fb_var_screeninfo vfb_default __devinitdata = {
+	.xres =		640,
+	.yres =		480,
+	.xres_virtual =	640,
+	.yres_virtual =	480,
+	.bits_per_pixel = 8,
+	.red =		{ 0, 8, 0 },
+      	.green =	{ 0, 8, 0 },
+      	.blue =		{ 0, 8, 0 },
+      	.activate =	FB_ACTIVATE_TEST,
+      	.height =	-1,
+      	.width =	-1,
+      	.pixclock =	20000,
+      	.left_margin =	64,
+      	.right_margin =	64,
+      	.upper_margin =	32,
+      	.lower_margin =	32,
+      	.hsync_len =	64,
+      	.vsync_len =	2,
+      	.vmode =	FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo vfb_fix __devinitdata = {
+	.id =		"Virtual FB",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	1,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static int vfb_enable __initdata = 0;	/* disabled by default */
+module_param(vfb_enable, bool, 0);
+
+static int vfb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info);
+static int vfb_set_par(struct fb_info *info);
+static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info);
+static int vfb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info);
+static int vfb_mmap(struct fb_info *info,
+		    struct vm_area_struct *vma);
+
+static struct fb_ops vfb_ops = {
+	.fb_read        = fb_sys_read,
+	.fb_write       = fb_sys_write,
+	.fb_check_var	= vfb_check_var,
+	.fb_set_par	= vfb_set_par,
+	.fb_setcolreg	= vfb_setcolreg,
+	.fb_pan_display	= vfb_pan_display,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_mmap	= vfb_mmap,
+};
+
+    /*
+     *  Internal routines
+     */
+
+static u_long get_line_length(int xres_virtual, int bpp)
+{
+	u_long length;
+
+	length = xres_virtual * bpp;
+	length = (length + 31) & ~31;
+	length >>= 3;
+	return (length);
+}
+
+    /*
+     *  Setting the video mode has been split into two parts.
+     *  First part, xxxfb_check_var, must not write anything
+     *  to hardware, it should only verify and adjust var.
+     *  This means it doesn't alter par but it does use hardware
+     *  data from it to check this var. 
+     */
+
+static int vfb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info)
+{
+	u_long line_length;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/*
+	 *  Some very basic checks
+	 */
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+	if (var->bits_per_pixel <= 1)
+		var->bits_per_pixel = 1;
+	else if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	if (var->xres_virtual < var->xoffset + var->xres)
+		var->xres_virtual = var->xoffset + var->xres;
+	if (var->yres_virtual < var->yoffset + var->yres)
+		var->yres_virtual = var->yoffset + var->yres;
+
+	/*
+	 *  Memory limit
+	 */
+	line_length =
+	    get_line_length(var->xres_virtual, var->bits_per_pixel);
+	if (line_length * var->yres_virtual > videomemorysize)
+		return -ENOMEM;
+
+	/*
+	 * Now that we checked it we alter var. The reason being is that the video
+	 * mode passed in might not work but slight changes to it might make it 
+	 * work. This way we let the user know what is acceptable.
+	 */
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGBA 5551 */
+		if (var->transp.length) {
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 10;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+		} else {	/* RGB 565 */
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 11;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 24:		/* RGB 888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	return 0;
+}
+
+/* This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the 
+ * change in par. For this driver it doesn't do much. 
+ */
+static int vfb_set_par(struct fb_info *info)
+{
+	info->fix.line_length = get_line_length(info->var.xres_virtual,
+						info->var.bits_per_pixel);
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info)
+{
+	if (regno >= 256)	/* no. of hw registers */
+		return 1;
+	/*
+	 * Program hardware... do anything you want with transp
+	 */
+
+	/* grayscale works only partially under directcolor */
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+		    (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Directcolor:
+	 *   var->{color}.offset contains start of bitfield
+	 *   var->{color}.length contains length of bitfield
+	 *   {hardwarespecific} contains width of RAMDAC
+	 *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
+	 *   RAMDAC[X] is programmed to (red, green, blue)
+	 *
+	 * Pseudocolor:
+	 *    var->{color}.offset is 0 unless the palette index takes less than
+	 *                        bits_per_pixel bits and is stored in the upper
+	 *                        bits of the pixel value
+	 *    var->{color}.length is set so that 1 << length is the number of available
+	 *                        palette entries
+	 *    cmap is not used
+	 *    RAMDAC[X] is programmed to (red, green, blue)
+	 *
+	 * Truecolor:
+	 *    does not use DAC. Usually 3 are present.
+	 *    var->{color}.offset contains start of bitfield
+	 *    var->{color}.length contains length of bitfield
+	 *    cmap is programmed to (red << red.offset) | (green << green.offset) |
+	 *                      (blue << blue.offset) | (transp << transp.offset)
+	 *    RAMDAC does not exist
+	 */
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		red = CNVT_TOHW(red, info->var.red.length);
+		green = CNVT_TOHW(green, info->var.green.length);
+		blue = CNVT_TOHW(blue, info->var.blue.length);
+		transp = CNVT_TOHW(transp, info->var.transp.length);
+		break;
+	case FB_VISUAL_DIRECTCOLOR:
+		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
+		green = CNVT_TOHW(green, 8);
+		blue = CNVT_TOHW(blue, 8);
+		/* hey, there is bug in transp handling... */
+		transp = CNVT_TOHW(transp, 8);
+		break;
+	}
+#undef CNVT_TOHW
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return 1;
+
+		v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			break;
+		case 16:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		case 24:
+		case 32:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+    /*
+     *  Pan or Wrap the Display
+     *
+     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+     */
+
+static int vfb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset < 0
+		    || var->yoffset >= info->var.yres_virtual
+		    || var->xoffset)
+			return -EINVAL;
+	} else {
+		if (var->xoffset + var->xres > info->var.xres_virtual ||
+		    var->yoffset + var->yres > info->var.yres_virtual)
+			return -EINVAL;
+	}
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+
+    /*
+     *  Most drivers don't need their own mmap function 
+     */
+
+static int vfb_mmap(struct fb_info *info,
+		    struct vm_area_struct *vma)
+{
+	unsigned long start = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long page, pos;
+
+	if (offset + size > info->fix.smem_len) {
+		return -EINVAL;
+	}
+
+	pos = (unsigned long)info->fix.smem_start + offset;
+
+	while (size > 0) {
+		page = vmalloc_to_pfn((void *)pos);
+		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
+	return 0;
+
+}
+
+#ifndef MODULE
+/*
+ * The virtual framebuffer driver is only enabled if explicitly
+ * requested by passing 'video=vfb:' (or any actual options).
+ */
+static int __init vfb_setup(char *options)
+{
+	char *this_opt;
+
+	vfb_enable = 0;
+
+	if (!options)
+		return 1;
+
+	vfb_enable = 1;
+
+	if (!*options)
+		return 1;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		/* Test disable for backwards compatibility */
+		if (!strcmp(this_opt, "disable"))
+			vfb_enable = 0;
+	}
+	return 1;
+}
+#endif  /*  MODULE  */
+
+    /*
+     *  Initialisation
+     */
+
+static int __devinit vfb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int retval = -ENOMEM;
+
+	/*
+	 * For real video cards we use ioremap.
+	 */
+	if (!(videomemory = rvmalloc(videomemorysize)))
+		return retval;
+
+	/*
+	 * VFB must clear memory to prevent kernel info
+	 * leakage into userspace
+	 * VGA-based drivers MUST NOT clear memory if
+	 * they want to be able to take over vgacon
+	 */
+	memset(videomemory, 0, videomemorysize);
+
+	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
+	if (!info)
+		goto err;
+
+	info->screen_base = (char __iomem *)videomemory;
+	info->fbops = &vfb_ops;
+
+	retval = fb_find_mode(&info->var, info, NULL,
+			      NULL, 0, NULL, 8);
+
+	if (!retval || (retval == 4))
+		info->var = vfb_default;
+	vfb_fix.smem_start = (unsigned long) videomemory;
+	vfb_fix.smem_len = videomemorysize;
+	info->fix = vfb_fix;
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err1;
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err2;
+	platform_set_drvdata(dev, info);
+
+	printk(KERN_INFO
+	       "fb%d: Virtual frame buffer device, using %ldK of video memory\n",
+	       info->node, videomemorysize >> 10);
+	return 0;
+err2:
+	fb_dealloc_cmap(&info->cmap);
+err1:
+	framebuffer_release(info);
+err:
+	rvfree(videomemory, videomemorysize);
+	return retval;
+}
+
+static int vfb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		rvfree(videomemory, videomemorysize);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+static struct platform_driver vfb_driver = {
+	.probe	= vfb_probe,
+	.remove = vfb_remove,
+	.driver = {
+		.name	= "vfb",
+	},
+};
+
+static struct platform_device *vfb_device;
+
+static int __init vfb_init(void)
+{
+	int ret = 0;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("vfb", &option))
+		return -ENODEV;
+	vfb_setup(option);
+#endif
+
+	if (!vfb_enable)
+		return -ENXIO;
+
+	ret = platform_driver_register(&vfb_driver);
+
+	if (!ret) {
+		vfb_device = platform_device_alloc("vfb", 0);
+
+		if (vfb_device)
+			ret = platform_device_add(vfb_device);
+		else
+			ret = -ENOMEM;
+
+		if (ret) {
+			platform_device_put(vfb_device);
+			platform_driver_unregister(&vfb_driver);
+		}
+	}
+
+	return ret;
+}
+
+module_init(vfb_init);
+
+#ifdef MODULE
+static void __exit vfb_exit(void)
+{
+	platform_device_unregister(vfb_device);
+	platform_driver_unregister(&vfb_driver);
+}
+
+module_exit(vfb_exit);
+
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */

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