⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fbtools.c

📁 linux下开源图片codec
💻 C
字号:
/* * some generic framebuffer device stuff * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <termios.h>#include <signal.h>#include <errno.h>#include <setjmp.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/wait.h>#include <sys/stat.h>#include <linux/kd.h>#include <linux/vt.h>#include <linux/fb.h>#include <asm/page.h>#include "fbtools.h"/* -------------------------------------------------------------------- *//* exported stuff                                                       */struct fb_fix_screeninfo   fb_fix;struct fb_var_screeninfo   fb_var;unsigned char             *fb_mem;int			   fb_mem_offset = 0;int                        fb_switch_state = FB_ACTIVE;/* -------------------------------------------------------------------- *//* internal variables                                                   */static int                       fb,tty;#if 0static int                       bpp,black,white;#endifstatic int                       orig_vt_no = 0;static struct vt_mode            vt_mode;static int                       kd_mode;static struct vt_mode            vt_omode;static struct termios            term;static struct fb_var_screeninfo  fb_ovar;static unsigned short            ored[256], ogreen[256], oblue[256];static struct fb_cmap            ocmap = { 0, 256, ored, ogreen, oblue };/* -------------------------------------------------------------------- *//* devices                                                              */struct DEVS {    char *fb0;    char *fbnr;    char *ttynr;};struct DEVS devs_default = {    fb0:   "/dev/fb0",    fbnr:  "/dev/fb%d",    ttynr: "/dev/tty%d",};struct DEVS devs_devfs = {    fb0:   "/dev/fb/0",    fbnr:  "/dev/fb/%d",    ttynr: "/dev/vc/%d",};struct DEVS *devices;static void dev_init(void){    struct stat dummy;    if (NULL != devices)	return;    if (0 == stat("/dev/.devfsd",&dummy))	devices = &devs_devfs;    else	devices = &devs_default;}/* -------------------------------------------------------------------- *//* console switching                                                    */extern int debug;static voidfb_switch_signal(int signal){    if (signal == SIGUSR1) {	/* release */	fb_switch_state = FB_REL_REQ;	if (debug)	    write(2,"vt: SIGUSR1\n",12);    }    if (signal == SIGUSR2) {	/* acquisition */	fb_switch_state = FB_ACQ_REQ;	if (debug)	    write(2,"vt: SIGUSR2\n",12);    }}voidfb_switch_release(){    ioctl(tty, VT_RELDISP, 1);    fb_switch_state = FB_INACTIVE;    if (debug)	write(2,"vt: release\n",12);}voidfb_switch_acquire(){    ioctl(tty, VT_RELDISP, VT_ACKACQ);    fb_switch_state = FB_ACTIVE;    if (debug)	write(2,"vt: acquire\n",12);}intfb_switch_init(){    struct sigaction act,old;    memset(&act,0,sizeof(act));    act.sa_handler  = fb_switch_signal;    sigemptyset(&act.sa_mask);    sigaction(SIGUSR1,&act,&old);    sigaction(SIGUSR2,&act,&old);        if (-1 == ioctl(tty,VT_GETMODE, &vt_mode)) {	perror("ioctl VT_GETMODE");	exit(1);    }    vt_mode.mode   = VT_PROCESS;    vt_mode.waitv  = 0;    vt_mode.relsig = SIGUSR1;    vt_mode.acqsig = SIGUSR2;        if (-1 == ioctl(tty,VT_SETMODE, &vt_mode)) {	perror("ioctl VT_SETMODE");	exit(1);    }    return 0;}/* -------------------------------------------------------------------- *//* initialisation & cleanup                                             */voidfb_memset (void *addr, int c, size_t len){#if 1 /* defined(__powerpc__) */    unsigned int i, *p;        i = (c & 0xff) << 8;    i |= i << 16;    len >>= 2;    for (p = addr; len--; p++)	*p = i;#else    memset(addr, c, len);#endif}static intfb_setmode(char *name){    FILE *fp;    char line[80],label[32],value[16];    int  geometry=0, timings=0;        /* load current values */    if (-1 == ioctl(fb,FBIOGET_VSCREENINFO,&fb_var)) {	perror("ioctl FBIOGET_VSCREENINFO");	exit(1);    }        if (NULL == name)	return -1;    if (NULL == (fp = fopen("/etc/fb.modes","r")))	return -1;    while (NULL != fgets(line,79,fp)) {	if (1 == sscanf(line, "mode \"%31[^\"]\"",label) &&	    0 == strcmp(label,name)) {	    /* fill in new values */	    fb_var.sync  = 0;	    fb_var.vmode = 0;	    while (NULL != fgets(line,79,fp) &&		   NULL == strstr(line,"endmode")) {		if (5 == sscanf(line," geometry %d %d %d %d %d",				&fb_var.xres,&fb_var.yres,				&fb_var.xres_virtual,&fb_var.yres_virtual,				&fb_var.bits_per_pixel))		    geometry = 1;		if (7 == sscanf(line," timings %d %d %d %d %d %d %d",				&fb_var.pixclock,				&fb_var.left_margin,  &fb_var.right_margin,				&fb_var.upper_margin, &fb_var.lower_margin,				&fb_var.hsync_len,    &fb_var.vsync_len))		    timings = 1;		if (1 == sscanf(line, " hsync %15s",value) &&		    0 == strcasecmp(value,"high"))		    fb_var.sync |= FB_SYNC_HOR_HIGH_ACT;		if (1 == sscanf(line, " vsync %15s",value) &&		    0 == strcasecmp(value,"high"))		    fb_var.sync |= FB_SYNC_VERT_HIGH_ACT;		if (1 == sscanf(line, " csync %15s",value) &&		    0 == strcasecmp(value,"high"))		    fb_var.sync |= FB_SYNC_COMP_HIGH_ACT;		if (1 == sscanf(line, " extsync %15s",value) &&		    0 == strcasecmp(value,"true"))		    fb_var.sync |= FB_SYNC_EXT;		if (1 == sscanf(line, " laced %15s",value) &&		    0 == strcasecmp(value,"true"))		    fb_var.vmode |= FB_VMODE_INTERLACED;		if (1 == sscanf(line, " double %15s",value) &&		    0 == strcasecmp(value,"true"))		    fb_var.vmode |= FB_VMODE_DOUBLE;	    }	    /* ok ? */	    if (!geometry || !timings)		return -1;	    /* set */	    fb_var.xoffset = 0;	    fb_var.yoffset = 0;	    if (-1 == ioctl(fb,FBIOPUT_VSCREENINFO,&fb_var))		perror("ioctl FBIOPUT_VSCREENINFO");	    /* look what we have now ... */	    if (-1 == ioctl(fb,FBIOGET_VSCREENINFO,&fb_var)) {		perror("ioctl FBIOGET_VSCREENINFO");		exit(1);	    }	    return 0;	}    }    return -1;}static voidfb_setvt(int vtno){    struct vt_stat vts;    char vtname[12];        if (vtno < 0) {	if (-1 == ioctl(tty,VT_OPENQRY, &vtno) || vtno == -1) {	    perror("ioctl VT_OPENQRY");	    exit(1);	}    }    vtno &= 0xff;    sprintf(vtname, devices->ttynr, vtno);    chown(vtname, getuid(), getgid());    if (-1 == access(vtname, R_OK | W_OK)) {	fprintf(stderr,"access %s: %s\n",vtname,strerror(errno));	exit(1);    }    switch (fork()) {    case 0:	break;    case -1:	perror("fork");	exit(1);    default:	exit(0);    }    close(tty);    close(0);    close(1);    close(2);    setsid();    open(vtname,O_RDWR);    dup(0);    dup(0);    if (-1 == ioctl(tty,VT_GETSTATE, &vts)) {	perror("ioctl VT_GETSTATE");	exit(1);    }    orig_vt_no = vts.v_active;    if (-1 == ioctl(tty,VT_ACTIVATE, vtno)) {	perror("ioctl VT_ACTIVATE");	exit(1);    }    if (-1 == ioctl(tty,VT_WAITACTIVE, vtno)) {	perror("ioctl VT_WAITACTIVE");	exit(1);    }}/* Hmm. radeonfb needs this. matroxfb doesn't. */static int fb_activate_current(int tty){    struct vt_stat vts;        if (-1 == ioctl(tty,VT_GETSTATE, &vts)) {	perror("ioctl VT_GETSTATE");	return -1;    }    if (-1 == ioctl(tty,VT_ACTIVATE, vts.v_active)) {	perror("ioctl VT_ACTIVATE");	return -1;    }    if (-1 == ioctl(tty,VT_WAITACTIVE, vts.v_active)) {	perror("ioctl VT_WAITACTIVE");	return -1;    }    return 0;}intfb_init(char *device, char *mode, int vt){    char   fbdev[16];    struct vt_stat vts;    dev_init();    tty = 0;    if (vt != 0)	fb_setvt(vt);    if (-1 == ioctl(tty,VT_GETSTATE, &vts)) {	fprintf(stderr,"ioctl VT_GETSTATE: %s (not a linux console?)\n",		strerror(errno));	exit(1);    }        if (NULL == device) {	device = getenv("FRAMEBUFFER");	if (NULL == device) {	    struct fb_con2fbmap c2m;	    if (-1 == (fb = open(devices->fb0,O_RDWR /* O_WRONLY */,0))) {		fprintf(stderr,"open %s: %s\n",devices->fb0,strerror(errno));		exit(1);	    }	    c2m.console = vts.v_active;	    if (-1 == ioctl(fb, FBIOGET_CON2FBMAP, &c2m)) {		perror("ioctl FBIOGET_CON2FBMAP");		exit(1);	    }	    close(fb);	    fprintf(stderr,"map: vt%02d => fb%d\n",		    c2m.console,c2m.framebuffer);	    sprintf(fbdev,devices->fbnr,c2m.framebuffer);	    device = fbdev;	}    }    /* get current settings (which we have to restore) */    if (-1 == (fb = open(device,O_RDWR /* O_WRONLY */))) {	fprintf(stderr,"open %s: %s\n",device,strerror(errno));	exit(1);    }    if (-1 == ioctl(fb,FBIOGET_VSCREENINFO,&fb_ovar)) {	perror("ioctl FBIOGET_VSCREENINFO");	exit(1);    }    if (-1 == ioctl(fb,FBIOGET_FSCREENINFO,&fb_fix)) {	perror("ioctl FBIOGET_FSCREENINFO");	exit(1);    }    if (fb_ovar.bits_per_pixel == 8 ||	fb_fix.visual == FB_VISUAL_DIRECTCOLOR) {	if (-1 == ioctl(fb,FBIOGETCMAP,&ocmap)) {	    perror("ioctl FBIOGETCMAP");	    exit(1);	}    }    if (-1 == ioctl(tty,KDGETMODE, &kd_mode)) {	perror("ioctl KDGETMODE");	exit(1);    }    if (-1 == ioctl(tty,VT_GETMODE, &vt_omode)) {	perror("ioctl VT_GETMODE");	exit(1);    }    tcgetattr(tty, &term);        /* switch mode */    fb_setmode(mode);        /* checks & initialisation */    if (-1 == ioctl(fb,FBIOGET_FSCREENINFO,&fb_fix)) {	perror("ioctl FBIOGET_FSCREENINFO");	exit(1);    }    if (fb_fix.type != FB_TYPE_PACKED_PIXELS) {	fprintf(stderr,"can handle only packed pixel frame buffers\n");	goto err;    }#if 0    switch (fb_var.bits_per_pixel) {    case 8:	white = 255; black = 0; bpp = 1;	break;    case 15:    case 16:	if (fb_var.green.length == 6)	    white = 0xffff;	else	    white = 0x7fff;	black = 0; bpp = 2;	break;    case 24:	white = 0xffffff; black = 0; bpp = fb_var.bits_per_pixel/8;	break;    case 32:	white = 0xffffff; black = 0; bpp = fb_var.bits_per_pixel/8;	fb_setpixels = fb_setpixels4;	break;    default:	fprintf(stderr, "Oops: %i bit/pixel ???\n",		fb_var.bits_per_pixel);	goto err;    }#endif    fb_mem_offset = (unsigned long)(fb_fix.smem_start) & (~PAGE_MASK);    fb_mem = mmap(NULL,fb_fix.smem_len+fb_mem_offset,		  PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);    if (-1L == (long)fb_mem) {	perror("mmap");	goto err;    }    /* move viewport to upper left corner */    if (fb_var.xoffset != 0 || fb_var.yoffset != 0) {	fb_var.xoffset = 0;	fb_var.yoffset = 0;	if (-1 == ioctl(fb,FBIOPAN_DISPLAY,&fb_var)) {	    perror("ioctl FBIOPAN_DISPLAY");	    goto err;	}    }    if (-1 == ioctl(tty,KDSETMODE, KD_GRAPHICS)) {	perror("ioctl KDSETMODE");	goto err;    }    fb_activate_current(tty);    /* cls */    fb_memset(fb_mem+fb_mem_offset,0,fb_fix.smem_len);    return fb; err:    fb_cleanup();    exit(1);}voidfb_cleanup(void){    /* restore console */    if (-1 == ioctl(fb,FBIOPUT_VSCREENINFO,&fb_ovar))	perror("ioctl FBIOPUT_VSCREENINFO");    if (-1 == ioctl(fb,FBIOGET_FSCREENINFO,&fb_fix))	perror("ioctl FBIOGET_FSCREENINFO");    if (fb_ovar.bits_per_pixel == 8 ||	fb_fix.visual == FB_VISUAL_DIRECTCOLOR) {	if (-1 == ioctl(fb,FBIOPUTCMAP,&ocmap))	    perror("ioctl FBIOPUTCMAP");    }    close(fb);    if (-1 == ioctl(tty,KDSETMODE, kd_mode))	perror("ioctl KDSETMODE");    if (-1 == ioctl(tty,VT_SETMODE, &vt_omode))	perror("ioctl VT_SETMODE");    if (orig_vt_no && -1 == ioctl(tty, VT_ACTIVATE, orig_vt_no))	perror("ioctl VT_ACTIVATE");    if (orig_vt_no && -1 == ioctl(tty, VT_WAITACTIVE, orig_vt_no))	perror("ioctl VT_WAITACTIVE");    tcsetattr(tty, TCSANOW, &term);    close(tty);}/* -------------------------------------------------------------------- *//* handle fatal errors                                                  */static jmp_buf fb_fatal_cleanup;static voidfb_catch_exit_signal(int signal){    siglongjmp(fb_fatal_cleanup,signal);}voidfb_catch_exit_signals(void){    struct sigaction act,old;    int termsig;    memset(&act,0,sizeof(act));    act.sa_handler = fb_catch_exit_signal;    sigemptyset(&act.sa_mask);    sigaction(SIGINT, &act,&old);    sigaction(SIGQUIT,&act,&old);    sigaction(SIGTERM,&act,&old);    sigaction(SIGABRT,&act,&old);    sigaction(SIGTSTP,&act,&old);    sigaction(SIGBUS, &act,&old);    sigaction(SIGILL, &act,&old);    sigaction(SIGSEGV,&act,&old);    if (0 == (termsig = sigsetjmp(fb_fatal_cleanup,0)))	return;    /* cleanup */    fb_cleanup();    fprintf(stderr,"Oops: %s\n",sys_siglist[termsig]);    exit(42);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -