Spoiler:
PHP Code:
// scroll.c - simple framebuffer scroller for kindle with (partially)
// broken eink display
//
// usage:
// scroll [percent] [type]
//
// percent: optional percent of display height to scroll (0 to 100, default = 10).
// type : optional display update type (value 0 to 2, default = 1):
// 0 = no flash (fast, but slight ghosting)
// 1 = quality (full flash update, cleanest display)
// 2 = speed (very fast, black and white only)
//
// *** Disclaimers and whatnot:
//
// This is just a simple quick-and-dirty hack.
// It could use some error checking, and more features.
//
// There is no "secret sauce" here (such as intellectual "Property",
// whatever that is), nothing to protect, no license needed.
//
// As always, please do not sue me if you poke your eye out with
// this code, or somehow manage to injure your brain or otherwise
// maim yourself, your stuff, or your loved ones with it.
//
// Enjoy, compliments of geekmaster... and twobob! ;)
//
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#define FB_UPDATE_AREA 0x46dd
int main(int argc, char** argv) {
int pct = 5; // 5% default
int fx = 1; // full flash update
int isx = 1; // x default - set argv 3 to invoke Y operation
int counter =0; // our counter thingies
int debug =0; // our debug thingies
__u8 bpp=0;
int y, x, height, width, width_bytes, fb_bytes;
struct fb_var_screeninfo screeninfo;
unsigned char *pfb = NULL, *psave = NULL;
struct update_area_t
{
int x1, y1, x2, y2, fx;
__u8 *buffer;
} ua;
// get optional command-line params
if (argc > 1) pct = atoi(argv[1]); // scroll percent (0-100)
if (argc > 2) fx = atoi(argv[2]); // update type (0-2)
if (argc > 3) isx = atoi(argv[2]); // make it X/Y/Debug configurable 0 = X, 1 = Y
if (argc > 4) debug = 1; // Setting the 4th arg enables debug output
// open framebuffer and get screen size (assume 4 bpp)
int fdFB = open("/dev/fb0", O_RDWR);
ioctl(fdFB, FBIOGET_VSCREENINFO, &screeninfo);
height = screeninfo.yres;
width = screeninfo.xres;
bpp = screeninfo.bits_per_pixel;
if (debug == 1)
{
printf("bpp is - %d\n",bpp);
printf("height is - %d\n",height);
printf("width is - %d\n",width);
}
if (bpp == 4 ) width_bytes = width / 2;
if (bpp == 8 ) width_bytes = width ;
fb_bytes = height * width_bytes;
// map and copy framebuffer
pfb = (unsigned char*)mmap(0, fb_bytes, PROT_READ|PROT_WRITE, MAP_SHARED, fdFB, 0);
psave = malloc(fb_bytes);
memcpy(psave, pfb, fb_bytes);
// copy swapped slices back to framebuffer
y = height * pct / 100;
x = width_bytes * pct / 100;
if (isx == 1)
{
while ( counter < fb_bytes )
{
memcpy(pfb + counter, psave + counter + x, width_bytes);
counter += width_bytes;
}
}
else
{
memcpy(pfb + y * width_bytes, psave, (height - y) * width_bytes);
memcpy(pfb, psave + (height - y) * width_bytes, y * width_bytes);
}
// trigger framebuffer update
ua.x1 = 0;
ua.y1 = 0;
ua.x2 = width;
ua.y2 = height;
ua.buffer = NULL;
ua.fx = fx; // update type
ioctl(fdFB, FB_UPDATE_AREA, &ua);
// cleanup
free (psave);
munmap(pfb, fb_bytes);
close(fdFB);
}
That should do it...
EDIT: I re-factored it to:
SETTING ARG1: scroll percent (-100->100) (will go in reverse) 5% default
SETTING ARG2: update type (0-2)
0 = no flash (fast, but slight ghosting)
1 = quality (full flash update, cleanest display) <- Default
2 = speed (very fast, black and white only)
SETTING ARG4: support debug output
SETTING ARG3: 0= X 1=Y (move in that axis) X is Default
Now should auto-detect 4 or 8 bits per pixel.
Will now ¨just work¨ on a 3 or a 4.