#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#include <linux/fb.h>

#define DEFAULT_DEVICE  "/dev/fb0"

/* ---------------------------------------------------------------------- */

char *fbdev  = NULL;

unsigned short            red[256],green[256],blue[256];
struct fb_cmap            cmap = { 0, 256, red, green, blue, NULL };
struct fb_fix_screeninfo  fix;
struct fb_var_screeninfo  var;

/* ---------------------------------------------------------------------- */

int
main(int argc, char *argv[])
{
    unsigned char             data[2048];
    int                       fd,x,y;
    
    if (NULL != getenv("FRAMEBUFFER")) {
	fbdev = getenv("FRAMEBUFFER");
    } else {
	fbdev = DEFAULT_DEVICE;
    }

    if (-1 == (fd = open(fbdev,O_RDWR))) {
	fprintf(stderr,"open %s: %s\n",fbdev,strerror(errno));
	exit(1);
    }

    if (-1 == ioctl(fd,FBIOGET_FSCREENINFO,&fix))
	perror("ioctl FBIOGET_FSCREENINFO");
    if (-1 == ioctl(fd,FBIOGET_VSCREENINFO,&var))
	perror("ioctl FBIOGET_VSCREENINFO");
    if (-1 == ioctl(fd,FBIOGETCMAP,&cmap))
	perror("ioctl FBIOGETCMAP");

    if (fix.type != FB_TYPE_PACKED_PIXELS ||
	fix.visual != FB_VISUAL_PSEUDOCOLOR ||
	var.bits_per_pixel != 8) {
	fprintf(stderr,"only 8bit pseudocolor is supported\n");
	exit(1);
    }

    printf("P6\n%d %d\n255\n",var.xres,var.yres);
    for (y = 0; y < var.yoffset; y++) {
	read(fd,data,var.xres);
    }
    for (y = 0; y < var.yres; y++) {
	read(fd,data,var.xres);
	for (x = 0; x < var.xres; x++) {
	    printf("%c%c%c",
		   red[data[x]],
		   green[data[x]],
		   blue[data[x]]);
	}
    }

    exit(0);
}
