📄 libfbx-init.c
字号:
/* * libfbx-init.c -- Main initilization file * (C)opyright 2000-2001 U4X Labs * * Written by: Paul Mundt <lethal@stampede.org> * Mike Bourgeous <nitrogen@u4x.org> * Mon Jul 24 04:55:24 EDT 2000 * * $Id: libfbx-init.c,v 1.35 2001/03/03 02:29:19 nitroglycerine Exp $ * * Implementation of a number of basic drawing functions for * the framebuffer system, to be used as a linked library in * other programs using the libfbx API. Forked from the fbdev-init * code to be a standalone library. * * See ChangeLog for modifications, CREDITS for credits. * * All source herein is copyright U4X Labs and its original author. * Any code modifications or additions are (C)opyright the original * author and U4X Labs respectively. * * libfbx is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * libfbx is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with libfbx; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <signal.h>#include <time.h>#include <math.h>#include <linux/fb.h>#include <linux/kd.h>#include <linux/vt.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <sys/user.h>#include <termios.h>#include <ctype.h>#include <libfbx/libfbx.h>#include <libfbx/libfbx-drivers.h>#include <asm/page.h>fb_surface *fb_screen = NULL;char *fbptr, *fb_device = NULL;int fbfd, fbptr_off;struct fb_var_screeninfo old_vinfo;int kd_mode;struct vt_mode old_vtmode, vtmode;struct termios term;unsigned short old_red[256], old_green[256], old_blue[256];struct fb_cmap old_map = {0, 256, old_red, old_green, old_blue, NULL};unsigned short red[256], green[256], blue[256];struct fb_cmap map_332 = {0, 256, red, green, blue, NULL};int tty;/* * Function: rand01() * Arguments: None * Returns: A random number * Description: Returns a random number between 0 and 1 */float rand01(){ return ((float)(rand() % RAND_MAX) / (float)RAND_MAX);}/* * Function: fb_setdev() * Arguments: Device to set to * Returns: 0 on success, -1 on failure * Description: Takes the specified device and sets it as the * global fb device to use. (Does not support * multihead, just allows you to specify an * alternate device). */int fb_setdev(char *setdev){ if (!setdev || setdev == NULL) return -1; if (access(setdev, F_OK) < 0) return -1; fb_device = setdev; return 0;}/* * Function: fb_finddev() * Arguments: None * Returns: Full path to framebuffer device * Description: Looks for the location of the framebuffer device * in the FRAMEBUFFER environment variable, and the * relative path in /dev (DFLT_FB). */char *fb_finddev(){ char *dev; if (fb_device != NULL) return fb_device; if ((dev = getenv("FRAMEBUFFER")) == NULL) { if (access(DFLT_FB,F_OK) == 0) { dev = DFLT_FB; setenv("FRAMEBUFFER", DFLT_FB, 1); } else if (access(DFLT_DEVFS_FB, F_OK) == 0) { dev = DFLT_DEVFS_FB; setenv("FRAMEBUFFER", DFLT_DEVFS_FB, 1); } } return dev;}/* * Function: fb_init() * Arguments: None * Returns: An fb_surface structure representing the screen. * Description: Locates and initializes the fb device. */int fb_init(){ fb_module *fb_module = fb_modules; char *dev, errstr[LEN]; if (fb_screen == NULL) { fb_screen = malloc(sizeof(fb_surface)); fb_screen->vinfo = calloc(1, sizeof(struct fb_var_screeninfo)); fb_screen->finfo = calloc(1, sizeof(struct fb_fix_screeninfo)); fb_screen->driver = calloc(1, sizeof(struct fb_driver)); fb_screen->driver->ops = calloc(1, sizeof(struct fb_driver_ops)); } else { /* Screen is already initialized */ return 1; } srand(time(0)); fb_make_332_map(&map_332); if ((dev = fb_finddev()) == NULL) { fprintf(stderr,"Cannot open %s, make sure it exists.\n", DFLT_FB); exit(1); } fb_font_init(); if ((fbfd = open(dev, O_RDWR)) < 0) { snprintf(errstr, LEN, "Error opening %s", dev); perror(errstr); exit(1); } if (ioctl(fbfd, FBIOGET_FSCREENINFO, fb_screen->finfo) < 0) { perror("Error reading fixed information"); exit(1); } if (ioctl(fbfd, FBIOGET_VSCREENINFO, fb_screen->vinfo) < 0) { perror("Error reading variable information"); exit(1); } if (ioctl(fbfd, FBIOGET_VSCREENINFO, &old_vinfo) < 0) { perror("Error reading variable information"); exit(1); } if (ioctl(fbfd, FBIOGETCMAP, &old_map) < 0) { perror("Error getting colormap"); exit(1); } if (fb_screen->finfo->visual == FB_VISUAL_DIRECTCOLOR || fb_screen->vinfo->bits_per_pixel == 8) if (ioctl(fbfd, FBIOPUTCMAP, &map_332) < 0) { perror("Error putting colormap"); exit(1); } if (ioctl(tty, KDGETMODE, &kd_mode) < 0) { perror("ioctl KDGETMODE"); exit(1); } if (ioctl(tty, VT_GETMODE, &old_vtmode) < 0) { perror("ioctl VT_GETMODE"); exit(1); } tcgetattr(tty, &term); fbptr = (char *)mmap(0, fb_screen->finfo->smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); fbptr_off = (unsigned long)fb_screen->finfo->smem_start & ~PAGE_MASK; fb_screen->width = fb_screen->vinfo->xres; fb_screen->height = fb_screen->vinfo->yres; strcpy(fb_screen->driver->id, fb_screen->finfo->id); fb_screen->driver->handle = NULL; while (fb_module->id != NULL) { if (strcmp(fb_screen->driver->id, fb_module->id) == 0) fb_load_module(fb_module->name); fb_module++; } switch (fb_screen->vinfo->bits_per_pixel) { case 8: fb_screen->pixel_size = 1; fb_screen->make_color = fb_make_color_8; break; case 15: fb_screen->pixel_size = 2; fb_screen->make_color = fb_make_color_15; fb_screen->vinfo->red.offset = 10; fb_screen->vinfo->red.length = 5; fb_screen->vinfo->green.offset = 5; fb_screen->vinfo->green.length = 5; fb_screen->vinfo->blue.offset = 0; fb_screen->vinfo->blue.length = 5; break; case 16: fb_screen->pixel_size = 2; fb_screen->make_color = fb_make_color_16; fb_screen->vinfo->red.offset = 11; fb_screen->vinfo->red.length = 5; fb_screen->vinfo->green.offset = 5; fb_screen->vinfo->green.length = 6; fb_screen->vinfo->blue.offset = 0; fb_screen->vinfo->blue.length = 5; break; case 24: fb_screen->pixel_size = 3; fb_screen->make_color = fb_make_color_24; fb_screen->vinfo->red.offset = 16; fb_screen->vinfo->red.length = 8; fb_screen->vinfo->green.offset = 8; fb_screen->vinfo->green.length = 8; fb_screen->vinfo->blue.offset = 0; fb_screen->vinfo->blue.length = 8; break; case 32: fb_screen->pixel_size = 4; fb_screen->make_color = fb_make_color_24; fb_screen->vinfo->red.offset = 16; fb_screen->vinfo->red.length = 8; fb_screen->vinfo->green.offset = 8; fb_screen->vinfo->green.length = 8; fb_screen->vinfo->blue.offset = 0; fb_screen->vinfo->blue.length = 8; break; default: fprintf(stderr, "Unknown color depth %d.\n" "Attempting to generate color.\n", fb_screen->vinfo->bits_per_pixel); fb_screen->pixel_size = 1; fb_screen->make_color = fb_make_color_unknown; break; } if (ioctl(fbfd, FBIOPUT_VSCREENINFO, fb_screen->vinfo) < 0) { perror("Couldn't set ideal mode at FBIOPUT_VSCREENINFO"); exit(1); } if (ioctl(fbfd, FBIOGET_VSCREENINFO, fb_screen->vinfo) < 0) { perror("ioctl FBIOGET_VSCREENINFO"); fb_cleanup(); exit(1); } fb_screen->bpp = fb_screen->vinfo->bits_per_pixel; fb_screen->line_size = fb_screen->finfo->line_length; fb_screen->buffer_size = fb_screen->finfo->smem_len; fb_screen->mem_offset = fbptr_off; fb_screen->mem_pointer = fbptr; fb_screen->red_size = fb_screen->vinfo->red.length; fb_screen->red_offset = fb_screen->vinfo->red.offset; fb_screen->green_size = fb_screen->vinfo->green.length; fb_screen->green_offset = fb_screen->vinfo->green.offset; fb_screen->blue_size = fb_screen->vinfo->blue.length; fb_screen->blue_offset = fb_screen->vinfo->blue.offset; /* atexit(fb_cleanup); */ if (ioctl(tty, KDSETMODE, KD_GRAPHICS)) { perror("ioctl KDSETMODE"); exit(1); } if (fb_screen->finfo->visual == FB_VISUAL_DIRECTCOLOR || fb_screen->vinfo->bits_per_pixel == 8) if (ioctl(fbfd, FBIOPUTCMAP, &map_332) < 0) { perror("ioctl FBIOPUTCMAP"); exit(1); } fb_screen->text.tab_size = 8; fb_screen->font.width = 8; fb_set_textcolor(fb_screen->make_color(0xff, 0xff, 0xff), 0x00); fb_handle_signals(); fb_screen->switch_state = FB_CONSOLE_ACTIVE; fb_switch_init(); if (fb_screen->driver->handle != NULL) fb_screen->driver->init(); fb_driver_ops_init(); return 0;}void (*old_handlers[2])(int sig);/* * Function: fb_cleanup() * Arguments: None * Returns: None * Description: unmaps memory and closes the * file descriptor. */void fb_cleanup(){ if (fb_screen != NULL) { if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &old_vinfo) < 0) perror("ioctl FBIOPUT_VSCREENINFO"); if (ioctl(fbfd, FBIOGET_FSCREENINFO, fb_screen->finfo) < 0) perror("ioctl FBIOGET_FSCREENINFO"); if (ioctl(fbfd, FBIOPUTCMAP, &old_map) < 0) perror("ioctl FBIOPUTCMAP"); if (fb_screen->driver->handle != NULL) { fb_screen->driver->exit(); fb_unload_module(); } munmap(fb_screen->mem_pointer, fb_screen->buffer_size); fbptr = NULL; fbptr_off = (int)NULL; /* shut up gcc */ close(fbfd); cfree(fb_screen->finfo); cfree(fb_screen->vinfo); cfree(fb_screen->driver->ops); cfree(fb_screen->driver); free(fb_screen); if (ioctl(tty, KDSETMODE, kd_mode) < 0) perror("ioctl KDSETMODE"); if (ioctl(tty, VT_SETMODE, &old_vtmode) < 0) perror("ioctl VT_SETMODE"); tcsetattr(tty, TCSANOW, &term); }}/* * Function: quit() * Arguments: signal number * Returns: None * Description: Function for use with signal() to * exit cleanly out of fb land. */void quit(int signum){ fb_cleanup(); fprintf(stderr,"Recieved fatal signal %d, exiting...\n", signum); exit(1);}/* * Function: fb_handle_signals() * Arguments: None * Returns: None * Description: Handles any signals we recieve. */void fb_handle_signals(){ int i, signals[] = { SIGINT, SIGSEGV }; for (i = 0; i < (sizeof(signals) / sizeof(int)); i++) if ((old_handlers[i] = signal(signals[i], quit)) == SIG_ERR) { fprintf(stderr,"Unable to set handler " "for signal %d.\n", signals[i]); exit(1); }}/* * Function: fb_driver_ops_init() * Arguments: None * Returns: None * Description: Determines which accelerated functions exist * in the driver. */void fb_driver_ops_init(){ if (fb_screen->driver->ops->blank != NULL) fb_screen->driver->ops->has_blank = 1; if (fb_screen->driver->ops->line != NULL) fb_screen->driver->ops->has_line = 1; if (fb_screen->driver->ops->fill_rect != NULL) fb_screen->driver->ops->has_fill_rect = 1; if (fb_screen->driver->ops->writec != NULL) fb_screen->driver->ops->has_writec = 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -