#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h> // contact the open(),close(),read(),write() and so on! 
#include <unistd.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>


#define DEVICE_NAME "/dev/graphics/fb0"//frame buffer device point 


int main(int argc,char **argv) 
{    
  int fd;
	struct fb_var_screeninfo vinfo;
	struct fb_fix_screeninfo finfo;
	long int screensize = 0; 
	void * fbp = 0;
	int ret, i, val; 
	int offset = 0;
	int y=0;

	printf("\n start framebuffer test \r\n"); 
	fd = open(DEVICE_NAME, O_RDWR); // Open frame buffer device and get the handle 
	printf("fd = %d \n", fd); 
	
	if (fd < 0) //open fail 
	{
		printf("open device %s error \n",DEVICE_NAME); 
	} 
	else 
	{
		if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo)) // get frame buffer frame_fix_screeninfo
		{
			close(fd);
			return -1;
		}

		if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo)) // get frame buffer frame_var_screeninfo
		{
			return -1;
		}        
		screensize = vinfo.xres*vinfo.yres*vinfo.bits_per_pixel / 8;
		screensize *= 2; //same with kenrel patch, we use two bufer
		fbp = (void *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
		printf("hjc>>>>screen size:%d\n", screensize);
		if (fbp == MAP_FAILED) 
		{
			printf("failed to mmap framebuffer!, update kernel patch for dual framebufer?\n");
			close(fd);
			
			return -1;
		}
		//commit the first buffer
		memset(fbp, 0x33, screensize);
		vinfo.activate |= FB_ACTIVATE_FORCE;

		if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo)) // put frame buffer frame_var_screeninfo
		{
			printf("failed to FBIOPUT_VSCREENINFO!\n");
			return -1;
		}

		y = vinfo.yres;
		for (i=0;i<100;i++) {
			//ping-pong two buffer
			val = (i % 2) ? 0x22 : 0xff;
			offset = (i % 2) ? screensize/2 : 0;
			memset(fbp+offset, val, screensize/2);
			vinfo.yoffset = (i % 2) ? y : 0;
			printf("hjc>>>>i:%d, val:0x%x, offset:0x%x\n", i, val, vinfo.yoffset);
			usleep(1000 * 5000);
			if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo)) // put frame buffer frame_var_screeninfo
			{
				printf("failed to FBIOPUT_VSCREENINFO!\n");
				return -1;
			}
		}

		munmap(fbp, screensize);
		
		ret = close(fd); //close device 
	} 
	
	return 0; 
}

