#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <linux/videodev2.h>
#include <linux/fb.h>
#include <linux/matroxfb.h>
#include <linux/ivtvfb.h>

#define W 720
#define H 576

#define IDX 0xff

static unsigned char osd[720*576];

int main(int argc, char **argv)
{
	char *device = "/dev/fb0";
	__u16 red[256], green[256], blue[256], transp[256];
	struct fb_cmap cmap;
	struct fb_var_screeninfo vi;
	struct ivtvfb_dma_frame df;
	int fd;
	int i;

	if (argc > 1) device = argv[1];

	fd = open(device, O_RDWR);

	if (fd == -1) {
		fprintf(stderr, "cannot open %s\n", device);
		exit(-1);
	}

	ioctl(fd, FBIOGET_VSCREENINFO, &vi);
	vi.nonstd = 0;
	vi.bits_per_pixel = 8;
	vi.xres = W;
	vi.yres = H;
	vi.xres_virtual = W;
	vi.yres_virtual = H;
	vi.xoffset = 0;
	vi.yoffset = 0;
	ioctl(fd, FBIOPUT_VSCREENINFO, &vi);

	cmap.red = red;
	cmap.green = green;
	cmap.blue = blue;
	cmap.transp = transp;
	cmap.start = 0;
	cmap.len = 256;
	ioctl(fd, FBIOGETCMAP, &cmap);
	printf("Ind: AA RR GG BB\n");
	for (i = 0; i < cmap.len; i++) {
		printf("%3d: %02x %02x %02x %02x\n", i,
			cmap.transp[i] >> 8, cmap.red[i] >> 8, cmap.green[i] >> 8, cmap.blue[i] >> 8);
	}

	memset(osd, IDX, sizeof(osd));
	df.source = osd;
	df.dest_offset = 0;
	df.count = sizeof(osd);
	ioctl(fd, IVTVFB_IOC_DMA_FRAME, &df);

	cmap.transp[IDX] = 0xffff;
	// go from black to white (opaque)
	for (i = 0; i < 256; i++) {
		cmap.red[IDX] = i << 8;
		cmap.blue[IDX] = i << 8;
		cmap.green[IDX] = i << 8;
		ioctl(fd, FBIOPUTCMAP, &cmap);
		ioctl(fd, FBIO_WAITFORVSYNC, 0);
	}
	// go from opaque to transparent
	for (i = 255; i >= 0; i--) {
		cmap.transp[IDX] = i << 8;
		ioctl(fd, FBIOPUTCMAP, &cmap);
		ioctl(fd, FBIO_WAITFORVSYNC, 0);
	}

	return 0;
}
