飞凌imx6ull移植tslib后解决校准是系统崩溃问题

飞凌原厂内核移植tslib和qt时

ioctl FBIOPUTCMAP: Inappropriate ioctl for device
ioctl FBIOPUTCMAP: Inappropriate ioctl for device
ioctl FBIOPUTCMAP: Inappropriate ioctl for device
ioctl FBIOPUTCMAP: Inappropriate ioctl for device
ioctl FBIOPUTCMAP: Inappropriate ioctl for device
ioctl FBIOPUTCMAP: Inappropriate ioctl for device
xres = 0, yres = 0
Took 20 samples...
Top left : X =  761 Y =    8
Took 15 samples...
Top right : X =  794 Y =  454
Took 14 samples...
Bot right : X =   13 Y =  454
Took 14 samples...
Bot left : X =   13 Y =    2
Took 17 samples...
Center : X =  768 Y =   26
44.620201 -0.016656 -0.194889
-57.297489 0.111690 0.025558
Calibration constants: 2924229 -1091 -12772 -3755048 7319 1674 65536 
Segmentation fault

问题原因:

print fix.smem_start
$2 = 2276458496
print fix.smem_len
$1 = 33554432

(gdb) print var.xres_virtual
$4 = 1024
(gdb) print var..yres_virtual
A syntax error in expression, near `.yres_virtual'.
(gdb) print var.yres_virtual
$5 = 1200
(gdb) print var.bits_per_pixel
$6 = 32

FBIOGET_FSCREENINFO 获取回来的空间大小太大,导致空间越界导致系统崩溃

参考 Linux驱动开发(9)------- framebuffer驱动详解-CSDN博客

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

// 宏定义
#define FBDEVICE	"/dev/fb0"
#define WIDTH		1024	
#define HEIGHT		600

#define WHITE		0xffffffff			// test ok
#define BLACK		0x00000000
#define RED			0xffff0000
#define GREEN		0xff00ff00			// test ok
#define BLUE		0xff0000ff			
#define GREENP		0x0000ff00			// 一样,说明前2个ff透明位不起作用

// 函数声明
void draw_back(unsigned int width, unsigned int height, unsigned int color);
void draw_line(unsigned int color);

// 全局变量
unsigned int *pfb = NULL;


int main(void)
{
	int fd = -1, ret = -1;
	
	
	struct fb_fix_screeninfo finfo = {0};
	struct fb_var_screeninfo vinfo = {0};
	
	// 第1步:打开设备
	fd = open(FBDEVICE, O_RDWR);
	if (fd < 0)
	{
		perror("open");
		return -1;
	}
	printf("open %s success.\n", FBDEVICE);
	
	// 第2步:获取设备的硬件信息
	ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	printf("smem_start = 0x%x, smem_len = %u.\n", finfo.smem_start, finfo.smem_len);
	
	ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
	printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
	printf("bpp = %u.\n", vinfo.bits_per_pixel);

	
	// 第3步:进行mmap
	unsigned long len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
	printf("len = %ld\n", len);
	pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (NULL == pfb)
	{
		perror("mmap");
		return -1;
	}
	printf("pfb = %p.\n", pfb);
	
	draw_back(WIDTH, HEIGHT, WHITE);
	draw_line(RED);
	

	close(fd);
	
	return 0;
}


//刷背景函数
void draw_back(unsigned int width, unsigned int height, unsigned int color)
{
	unsigned int x, y;
	
	for (y=0; y<height; y++)
	{
		for (x=0; x<width; x++)
		{
			*(pfb + y * WIDTH + x) = color;
		}
	}
}

//画线函数
void draw_line(unsigned int color)
{
	unsigned int x, y;
	
	for (x=50; x<600; x++)
	{
		*(pfb + 200 * WIDTH + x) = color;
	}
}

可使用FBIOGET_VSCREENINFO 大小修改内存空间

修改

	printf("xres = %u, yres = %u.\n", var.xres, var.yres);
	printf("xres_virtual = %u, yres_virtual = %u.\n", var.xres_virtual, var.yres_virtual);
	printf("bpp = %u.\n", var.bits_per_pixel);

	
	// 第3步:进行mmap
	unsigned long len = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
	printf("len = %ld\n", len);

	// fbuffer = mmap(NULL,
	// 	       fix.smem_len,
	// 	       PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
	// 	       fb_fd,
	// 	       0);
	fbuffer = mmap(NULL,
		       len,
		       PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
		       fb_fd,
		       0);

void close_framebuffer(void)
{
	unsigned long len = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
	memset(fbuffer, 0, len);
	munmap(fbuffer, len);
	// memset(fbuffer, 0, fix.smem_len);
	// munmap(fbuffer, fix.smem_len);
	close(fb_fd);

	if (strcmp(consoledevice, "none") != 0) {
		if (ioctl(con_fd, KDSETMODE, KD_TEXT) < 0)
			perror("KDSETMODE");

		if (last_vt >= 0)
			if (ioctl(con_fd, VT_ACTIVATE, last_vt))
				perror("VT_ACTIVATE");

		close(con_fd);
	}
	printf("12\n");
	free(line_addr);
	printf("13\n");
	xres = 0;
	yres = 0;
	rotation = 0;
}

tslib 编译 使用版本1.22
./configure --host=arm-linux-gnueabihf --prefix=/home/lin/qt/tslib/tslib-1.22/arm-tslib

修改后校准后触摸正常。如果有问题后续更新

涉及到两个文件

ts_calibrate.c

/*
 *  tslib/tests/ts_calibrate.c
 *
 *  Copyright (C) 2001 Russell King.
 *
 * This file is placed under the GPL.  Please see the file
 * COPYING for more details.
 *
 * SPDX-License-Identifier: GPL-2.0+
 *
 *
 * Graphical touchscreen calibration tool. This writes the configuration
 * file used by tslib's "linear" filter plugin module to transform the
 * touch samples according to the calibration.
 */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <getopt.h>
#include <errno.h>

#include "tslib.h"

#include "fbutils.h"
#include "testutils.h"
#include "ts_calibrate.h"

#define CROSS_BOUND_DIST	50
#define VALIDATE_BOUNDARY_MIN	10
#define VALIDATE_LOOPS_DEFAULT	3
//#define TS_POINTERCAL "/etc/pointercal"
static int palette[] = {
	0x000000, 0xffe080, 0xffffff, 0xe0c0a0, 0xff0000, 0x00ff00
};
#define NR_COLORS (sizeof(palette) / sizeof(palette[0]))

static void sig(int sig)
{
	close_framebuffer();
	fflush(stderr);
	printf("signal %d caught\n", sig);
	fflush(stdout);
	exit(1);
}

static unsigned int getticks()
{
	static struct timeval ticks = {0};
	static unsigned int val = 0;

	gettimeofday(&ticks, NULL);
	val = ticks.tv_sec * 1000;
	val += ticks.tv_usec / 1000;

	return val;
}

static void get_sample(struct tsdev *ts, calibration *cal,
		       int index, int x, int y, char *name, short redo)
{
	static int last_x = -1, last_y;

	if (redo) {
		last_x = -1;
		last_y = 0;
	}

	if (last_x != -1) {
#define NR_STEPS 10
		int dx = ((x - last_x) << 16) / NR_STEPS;
		int dy = ((y - last_y) << 16) / NR_STEPS;
		int i;

		last_x <<= 16;
		last_y <<= 16;
		for (i = 0; i < NR_STEPS; i++) {
			put_cross(last_x >> 16, last_y >> 16, 2 | XORMODE);
			usleep(1000);
			put_cross(last_x >> 16, last_y >> 16, 2 | XORMODE);
			last_x += dx;
			last_y += dy;
		}
	}

	put_cross(x, y, 2 | XORMODE);
	getxy(ts, &cal->x[index], &cal->y[index]);
	put_cross(x, y, 2 | XORMODE);

	last_x = cal->xfb[index] = x;
	last_y = cal->yfb[index] = y;

	printf("%s : X = %4d Y = %4d\n", name, cal->x[index], cal->y[index]);
}

static int validate_sample(struct tsdev *ts, int x, int y, char *name,
			   int boundary)
{
	static int last_x = -1, last_y;
	int read_x, read_y;
	int ret;

	if (last_x != -1) {
#define NR_STEPS 10
		int dx = ((x - last_x) << 16) / NR_STEPS;
		int dy = ((y - last_y) << 16) / NR_STEPS;
		int i;

		last_x <<= 16;
		last_y <<= 16;
		for (i = 0; i < NR_STEPS; i++) {
			put_cross(last_x >> 16, last_y >> 16, 2 | XORMODE);
			usleep(1000);
			put_cross(last_x >> 16, last_y >> 16, 2 | XORMODE);
			last_x += dx;
			last_y += dy;
		}
	}

	put_cross(x, y, 2 | XORMODE);
	getxy_validate(ts, &read_x, &read_y);

	if ((read_x > x - boundary) && (read_x < x + boundary) &&
	    (read_y > y - boundary) && (read_y < y + boundary)) {
		ret = 0;
	} else {
		ret = -1;
	}
	put_cross(x, y, 2 | XORMODE);

	last_x = x;
	last_y = y;

	printf("%s : X = %4d(%4d) Y = %4d(%4d) %s\n",
	       name, read_x, x, read_y, y,
	       ret ? "fail" : "pass");

	return ret;
}

static int ts_validate(struct tsdev *ts, int boundary, unsigned int loops, int timeout)
{
	int ret;
	char textbuf[64];
	int random_x, random_y;
	unsigned int i;

	if (boundary < VALIDATE_BOUNDARY_MIN ||
	    boundary > (int)xres || boundary > (int)yres) {
		boundary = VALIDATE_BOUNDARY_MIN;
		fprintf(stderr, "Boundary out of range. Using %d\n",
			boundary);
	}

	if (loops == 0)
		loops = VALIDATE_LOOPS_DEFAULT;

	snprintf(textbuf, sizeof(textbuf),
		 "Validate touchscreen calibration with boundary %d.",
		 boundary);

	put_string_center(xres / 2, yres / 4, textbuf, 1);
	put_string_center(xres / 2, yres / 4 + 20,
			  "Touch crosshair to validate", 2);

	for (i = 0; i < loops; i++) {
		srand(time(NULL));
		random_x = rand() % xres;
		random_y = rand() % yres;
		ret = validate_sample(ts, random_x, random_y, "random", boundary);
		if (ret)
			goto done;
	}

done:
	fillrect(0, 0, xres - 1, yres - 1, 0);
	put_string_center(xres / 2, yres / 4, textbuf, 1);

	if (timeout == 0) {
		close_framebuffer();
		ts_close(ts);
		return ret;
	}

	if (!ret) {
		printf("Validation passed.\n");
		put_string_center(xres / 2, yres / 4 + 20,
				  "Validation passed", 5);
	} else {
		printf("Validation failed.\n");
		put_string_center(xres / 2, yres / 4 + 20,
				  "Validation failed", 4);
	}

	if (timeout > 0) {
		sleep(timeout);
		close_framebuffer();
		ts_close(ts);
	}

	return ret;
}

static void clearbuf(struct tsdev *ts)
{
	int fd = ts_fd(ts);
	fd_set fdset;
	struct timeval tv;
	int nfds;
	struct ts_sample sample;

	while (1) {
		FD_ZERO(&fdset);
		FD_SET(fd, &fdset);

		tv.tv_sec = 0;
		tv.tv_usec = 0;

		nfds = select(fd + 1, &fdset, NULL, NULL, &tv);
		if (nfds == 0)
			break;

		if (ts_read_raw(ts, &sample, 1) < 0) {
			perror("ts_read_raw");
			exit(1);
		}
	}
}

static void help(void)
{
	ts_print_ascii_logo(16);
	print_version();

	printf("\n");
	printf("Usage: ts_calibrate [-r <rotate_value>] [--version]\n");
	printf("\n");
	printf("-r --rotate\n");
	printf("        <rotate_value> 0 ... no rotation; 0 degree (default)\n");
	printf("                       1 ... clockwise orientation; 90 degrees\n");
	printf("                       2 ... upside down orientation; 180 degrees\n");
	printf("                       3 ... counterclockwise orientation; 270 degrees\n");
	printf("-t --min_interval\n");
	printf("                       minimum time in ms between touch presses\n");
	printf("-c --validate\n");
	printf("                       validate the current calibration\n");
	printf("-b --boundary\n");
	printf("                       boundary criteria in validation mode\n");
	printf("-l --loops\n");
	printf("                       number of crosses to touch in validation mode\n");
	printf("-s --timeout\n");
	printf("                       result screen timeout in seconds in validation mode\n");
	printf("                       -1 ... no timeout\n");
	printf("                        0 ... no result screen (quit immediately)\n");
	printf("                        5 ... 5s timeout for result screen (default)\n");
	printf("-h --help\n");
	printf("                       print this help text\n");
	printf("-v --version\n");
	printf("                       print version information only\n");
	printf("\n");
	printf("Example (Linux): ts_calibrate -r $(cat /sys/class/graphics/fbcon/rotate)\n");
	printf("\n");
}

int main(int argc, char **argv)
{
	struct tsdev *ts;
	calibration cal = {
		.x = { 0 },
		.y = { 0 },
	};
	int cal_fd;
	char cal_buffer[256];
	char *calfile = NULL;
	unsigned int i, len;
	unsigned int tick = 0;
	unsigned int min_interval = 0;
	int boundary = VALIDATE_BOUNDARY_MIN;
	int validate_timeout = 5;
	unsigned int validate_loops = 0;
	short validate_only = 0;

	signal(SIGSEGV, sig);
	signal(SIGINT, sig);
	signal(SIGTERM, sig);

	while (1) {
		const struct option long_options[] = {
			{ "help",         no_argument,       NULL, 'h' },
			{ "rotate",       required_argument, NULL, 'r' },
			{ "version",      no_argument,       NULL, 'v' },
			{ "min_interval", required_argument, NULL, 't' },
			{ "validate",     no_argument,       NULL, 'c' },
			{ "boundary",     required_argument, NULL, 'b' },
			{ "loop",         required_argument, NULL, 'l' },
			{ "timeout",      required_argument, NULL, 's' },
		};

		int option_index = 0;
		int c = getopt_long(argc, argv, "hvr:t:cb:l:s:", long_options, &option_index);

		errno = 0;
		if (c == -1)
			break;

		switch (c) {
		case 'h':
			help();
			return 0;

		case 'v':
			print_version();
			return 0;

		case 'r':
			/* extern in fbutils.h */
			rotation = atoi(optarg);
			if (rotation < 0 || rotation > 3) {
				help();
				return 0;
			}
			break;

		case 't':
			min_interval = atoi(optarg);
			if (min_interval > 10000) {
				fprintf(stderr, "Minimum interval too long\n");
				return 0;
			}
			break;

		case 'c':
			validate_only = 1;
			break;

		case 'b':
			if (!validate_only) {
				fprintf(stderr, "--boundary is only available with --validate\n");
				help();
				return 0;
			}

			boundary = atoi(optarg);
			break;

		case 'l':
			if (!validate_only) {
				fprintf(stderr, "--loop is only available with --validate\n");
				help();
				return 0;
			}

			validate_loops = atoi(optarg);
			break;

		case 's':
			if (!validate_only) {
				fprintf(stderr, "--timeout is only available with --validate\n");
				help();
				return 0;
			}

			validate_timeout = atoi(optarg);
			break;

		default:
			help();
			return 0;
		}

		if (errno) {
			char str[9];
			sprintf(str, "option ?");
			str[7] = c & 0xff;
			perror(str);
		}
	}

	ts = ts_setup(NULL, 0);
	if (!ts) {
		perror("ts_setup");
		exit(1);
	}

	if (open_framebuffer()) {
		close_framebuffer();
		ts_close(ts);
		exit(1);
	}

	for (i = 0; i < NR_COLORS; i++)
		setcolor(i, palette[i]);

	if (validate_only)
		return ts_validate(ts, boundary, validate_loops, validate_timeout);

	put_string_center(xres / 2, yres / 4,
			  "Touchscreen calibration utility", 1);
	put_string_center(xres / 2, yres / 4 + 20,
			  "Touch crosshair to calibrate", 2);

	printf("xres = %d, yres = %d\n", xres, yres);

	/* Clear the buffer */
	clearbuf(ts);

	/* ignore rotation for calibration. only save it.*/
	int rotation_temp = rotation;
	int xres_temp = xres;
	int yres_temp = yres;
	rotation = 0;
	xres = xres_orig;
	yres = yres_orig;

	short redo = 0;

redocalibration:
	tick = getticks();
	get_sample(ts, &cal, 0, CROSS_BOUND_DIST,        CROSS_BOUND_DIST,        "Top left", redo);
	redo = 0;
	if (getticks() - tick < min_interval) {
		redo = 1;
	#ifdef DEBUG
		printf("ts_calibrate: time before touch press < %dms. restarting.\n",
			min_interval);
	#endif
		goto redocalibration;
	}
	clearbuf(ts);

	tick = getticks();
	get_sample(ts, &cal, 1, xres - CROSS_BOUND_DIST, CROSS_BOUND_DIST,        "Top right", redo);
	if (getticks() - tick < min_interval) {
		redo = 1;
	#ifdef DEBUG
		printf("ts_calibrate: time before touch press < %dms. restarting.\n",
			min_interval);
	#endif
		goto redocalibration;
	}
	clearbuf(ts);

	tick = getticks();
	get_sample(ts, &cal, 2, xres - CROSS_BOUND_DIST, yres - CROSS_BOUND_DIST, "Bot right", redo);
	if (getticks() - tick < min_interval) {
		redo = 1;
	#ifdef DEBUG
		printf("ts_calibrate: time before touch press < %dms. restarting.\n",
			min_interval);
	#endif
		goto redocalibration;
	}
	clearbuf(ts);

	tick = getticks();
	get_sample(ts, &cal, 3, CROSS_BOUND_DIST,        yres - CROSS_BOUND_DIST, "Bot left", redo);
	if (getticks() - tick < min_interval) {
		redo = 1;
	#ifdef DEBUG
		printf("ts_calibrate: time before touch press < %dms. restarting.\n",
			min_interval);
	#endif
		goto redocalibration;
	}
	clearbuf(ts);

	tick = getticks();
	get_sample(ts, &cal, 4, xres_orig / 2,  yres_orig / 2,  "Center", redo);
	if (getticks() - tick < min_interval) {
		redo = 1;
	#ifdef DEBUG
		printf("ts_calibrate: time before touch press < %dms. restarting.\n",
			min_interval);
	#endif
		goto redocalibration;
	}

	rotation = rotation_temp;
	xres = xres_temp;
	yres = yres_temp;

	if (perform_calibration (&cal)) {
		printf("Calibration constants: ");
		for (i = 0; i < 7; i++)
			printf("%d ", cal.a[i]);
		printf("\n");
		
		if ((calfile = getenv("TSLIB_CALIBFILE")) != NULL) {
			cal_fd = open(calfile, O_CREAT | O_TRUNC | O_RDWR,
				      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
					  
		} else {
			cal_fd = open(TS_POINTERCAL, O_CREAT | O_TRUNC | O_RDWR,
				      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
				  	
		}
		
		if (cal_fd < 0) {
			perror("open");
			close_framebuffer();
			ts_close(ts);
			exit(1);
		}
	
		printf("1......%p\n",cal_buffer);
		len = sprintf(cal_buffer, "%d %d %d %d %d %d %d %d %d %d",
			      cal.a[1], cal.a[2], cal.a[0],
			      cal.a[4], cal.a[5], cal.a[3], cal.a[6],
			      xres_orig, yres_orig, rotation);
  
		if (write(cal_fd, cal_buffer, len) == -1) {
			perror("write");
			close_framebuffer();
			ts_close(ts);
			exit(1);
		}
	
		close(cal_fd);
		i = 0;
	} else {
		printf("Calibration failed.\n");
		i = -1;
	}
	printf("2\n");
	fillrect(0, 0, xres - 1, yres - 1, 0);
	printf("3\n");
	close_framebuffer();
	printf("4\n");
	ts_close(ts);
	printf("5\n");
	return i;
}
/*
 * fbutils-linux.c
 *
 * Utility routines for framebuffer interaction
 *
 * Copyright 2002 Russell King and Doug Lowder
 *
 * This file is placed under the GPL.  Please see the
 * file COPYING for details.
 *
 * SPDX-License-Identifier: GPL-2.0+
 */

#include "config.h"

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

#include <linux/vt.h>
#include <linux/kd.h>
#include <linux/fb.h>

#include "font.h"
#include "fbutils.h"

union multiptr {
	uint8_t *p8;
	uint16_t *p16;
	uint32_t *p32;
};

static int32_t con_fd, last_vt = -1;
static struct fb_fix_screeninfo fix;
static struct fb_var_screeninfo var;
static unsigned char *fbuffer;
static unsigned char **line_addr;
static int32_t fb_fd;
static int32_t bytes_per_pixel;
static uint32_t transp_mask;
static uint32_t colormap[256];
uint32_t xres, yres;
uint32_t xres_orig, yres_orig;
int8_t rotation;
int8_t alternative_cross;

static char *defaultfbdevice = "/dev/fb0";
static char *defaultconsoledevice = "/dev/tty";
static char *fbdevice;
static char *consoledevice;

#define VTNAME_LEN 128

int open_framebuffer(void)
{
	struct vt_stat vts;
	char vtname[VTNAME_LEN];
	int32_t fd, nr;
	uint32_t y, addr;

	if ((fbdevice = getenv("TSLIB_FBDEVICE")) == NULL)
		fbdevice = defaultfbdevice;

	if ((consoledevice = getenv("TSLIB_CONSOLEDEVICE")) == NULL)
		consoledevice = defaultconsoledevice;

	if (strcmp(consoledevice, "none") != 0) {
		if (strlen(consoledevice) >= VTNAME_LEN)
			return -1;

		sprintf(vtname, "%s%d", consoledevice, 1);
		fd = open(vtname, O_WRONLY);
		if (fd < 0) {
			perror("open consoledevice");
			return -1;
		}

		if (ioctl(fd, VT_OPENQRY, &nr) < 0) {
			close(fd);
			perror("ioctl VT_OPENQRY");
			return -1;
		}
		close(fd);

		sprintf(vtname, "%s%d", consoledevice, nr);

		con_fd = open(vtname, O_RDWR | O_NDELAY);
		if (con_fd < 0) {
			perror("open tty");
			return -1;
		}

		if (ioctl(con_fd, VT_GETSTATE, &vts) == 0)
			last_vt = vts.v_active;

		if (ioctl(con_fd, VT_ACTIVATE, nr) < 0) {
			perror("VT_ACTIVATE");
			close(con_fd);
			return -1;
		}

#ifndef TSLIB_NO_VT_WAITACTIVE
		if (ioctl(con_fd, VT_WAITACTIVE, nr) < 0) {
			perror("VT_WAITACTIVE");
			close(con_fd);
			return -1;
		}
#endif

		if (ioctl(con_fd, KDSETMODE, KD_GRAPHICS) < 0) {
			perror("KDSETMODE");
			close(con_fd);
			return -1;
		}

	}

	fb_fd = open(fbdevice, O_RDWR);
	if (fb_fd == -1) {
		perror("open fbdevice");
		return -1;
	}

	if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix) < 0) {
		perror("ioctl FBIOGET_FSCREENINFO");
		close(fb_fd);
		return -1;
	}

	if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var) < 0) {
		perror("ioctl FBIOGET_VSCREENINFO");
		close(fb_fd);
		return -1;
	}

	xres_orig = var.xres;
	yres_orig = var.yres;

	if (rotation & 1) {
		/* 1 or 3 */
		y = var.yres;
		yres = var.xres;
		xres = y;
	} else {
		/* 0 or 2 */
		xres = var.xres;
		yres = var.yres;
	}

	printf("xres = %u, yres = %u.\n", var.xres, var.yres);
	printf("xres_virtual = %u, yres_virtual = %u.\n", var.xres_virtual, var.yres_virtual);
	printf("bpp = %u.\n", var.bits_per_pixel);

	
	// 第3步:进行mmap
	unsigned long len = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
	printf("len = %ld\n", len);

	// fbuffer = mmap(NULL,
	// 	       fix.smem_len,
	// 	       PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
	// 	       fb_fd,
	// 	       0);
	fbuffer = mmap(NULL,
		       len,
		       PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
		       fb_fd,
		       0);
	if (fbuffer == (unsigned char *)-1) {
		perror("mmap framebuffer");
		close(fb_fd);
		return -1;
	}
	//memset(fbuffer, 0, fix.smem_len);
	memset(fbuffer, 0, len);
	bytes_per_pixel = (var.bits_per_pixel + 7) / 8;
	transp_mask = ((1 << var.transp.length) - 1) <<
		var.transp.offset; /* transp.length unlikely > 32 */
	line_addr = malloc(sizeof(*line_addr) * var.yres_virtual);
	addr = 0;
	for (y = 0; y < var.yres_virtual; y++, addr += fix.line_length)
		line_addr[y] = fbuffer + addr;

	return 0;
}

void close_framebuffer(void)
{
	unsigned long len = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
	memset(fbuffer, 0, len);
	munmap(fbuffer, len);
	// memset(fbuffer, 0, fix.smem_len);
	// munmap(fbuffer, fix.smem_len);
	close(fb_fd);

	if (strcmp(consoledevice, "none") != 0) {
		if (ioctl(con_fd, KDSETMODE, KD_TEXT) < 0)
			perror("KDSETMODE");

		if (last_vt >= 0)
			if (ioctl(con_fd, VT_ACTIVATE, last_vt))
				perror("VT_ACTIVATE");

		close(con_fd);
	}
	printf("12\n");
	free(line_addr);
	printf("13\n");
	xres = 0;
	yres = 0;
	rotation = 0;
}

void put_cross(int32_t x, int32_t y, uint32_t colidx)
{
	line(x - 10, y, x - 2, y, colidx);
	line(x + 2, y, x + 10, y, colidx);
	line(x, y - 10, x, y - 2, colidx);
	line(x, y + 2, x, y + 10, colidx);

	if (!alternative_cross) {
		line(x - 6, y - 9, x - 9, y - 9, colidx + 1);
		line(x - 9, y - 8, x - 9, y - 6, colidx + 1);
		line(x - 9, y + 6, x - 9, y + 9, colidx + 1);
		line(x - 8, y + 9, x - 6, y + 9, colidx + 1);
		line(x + 6, y + 9, x + 9, y + 9, colidx + 1);
		line(x + 9, y + 8, x + 9, y + 6, colidx + 1);
		line(x + 9, y - 6, x + 9, y - 9, colidx + 1);
		line(x + 8, y - 9, x + 6, y - 9, colidx + 1);
	} else if (alternative_cross == 1) {
		line(x - 7, y - 7, x - 4, y - 4, colidx + 1);
		line(x - 7, y + 7, x - 4, y + 4, colidx + 1);
		line(x + 4, y - 4, x + 7, y - 7, colidx + 1);
		line(x + 4, y + 4, x + 7, y + 7, colidx + 1);
	}
}

static void put_char(int32_t x, int32_t y, int32_t c, int32_t colidx)
{
	int32_t i, j, bits;

	for (i = 0; i < font_vga_8x8.height; i++) {
		bits = font_vga_8x8.data[font_vga_8x8.height * c + i];
		for (j = 0; j < font_vga_8x8.width; j++, bits <<= 1)
			if (bits & 0x80)
				pixel(x + j, y + i, colidx);
	}
}

void put_string(int32_t x, int32_t y, char *s, uint32_t colidx)
{
	int32_t i;

	for (i = 0; *s; i++, x += font_vga_8x8.width, s++)
		put_char (x, y, *s, colidx);
}

void put_string_center(int32_t x, int32_t y, char *s, uint32_t colidx)
{
	size_t sl = strlen(s);

	put_string(x - (sl / 2) * font_vga_8x8.width,
		   y - font_vga_8x8.height / 2, s, colidx);
}

void setcolor(uint32_t colidx, uint32_t value)
{
	uint32_t res;
	uint16_t red, green, blue;
	struct fb_cmap cmap;

	if (colidx > 255) {
#ifdef DEBUG
		fprintf(stderr, "WARNING: color index = %u, must be <256\n",
			colidx);
#endif
		return;
	}

	switch (bytes_per_pixel) {
	default:
	case 1:
		res = colidx;
		red = (value >> 8) & 0xff00;
		green = value & 0xff00;
		blue = (value << 8) & 0xff00;
		cmap.start = colidx;
		cmap.len = 1;
		cmap.red = &red;
		cmap.green = &green;
		cmap.blue = &blue;
		cmap.transp = NULL;

		if (ioctl(fb_fd, FBIOPUTCMAP, &cmap) < 0)
			perror("ioctl FBIOPUTCMAP");
		break;
	case 2:
	case 3:
	case 4:
		red = (value >> 16) & 0xff;
		green = (value >> 8) & 0xff;
		blue = value & 0xff;
		res = ((red >> (8 - var.red.length)) << var.red.offset) |
		      ((green >> (8 - var.green.length)) << var.green.offset) |
		      ((blue >> (8 - var.blue.length)) << var.blue.offset);
	}
	colormap[colidx] = res;
}

static void __pixel_loc(int32_t x, int32_t y, union multiptr *loc)
{
	switch (rotation) {
	case 0:
	default:
		loc->p8 = line_addr[y] + x * bytes_per_pixel;
		break;
	case 1:
		loc->p8 = line_addr[x] + (yres - y - 1) * bytes_per_pixel;
		break;
	case 2:
		loc->p8 = line_addr[yres - y - 1] + (xres - x - 1) * bytes_per_pixel;
		break;
	case 3:
		loc->p8 = line_addr[xres - x - 1] + y * bytes_per_pixel;
		break;
	}
}

static inline void __setpixel(union multiptr loc, uint32_t xormode, uint32_t color)
{
	switch (bytes_per_pixel) {
	case 1:
	default:
		if (xormode)
			*loc.p8 ^= color;
		else
			*loc.p8 = color;
		*loc.p8 |= transp_mask;
		break;
	case 2:
		if (xormode)
			*loc.p16 ^= color;
		else
			*loc.p16 = color;
		*loc.p16 |= transp_mask;
		break;
	case 3:
		if (xormode) {
			*loc.p8++ ^= (color >> 16) & 0xff;
			*loc.p8++ ^= (color >> 8) & 0xff;
			*loc.p8 ^= color & 0xff;
		} else {
			*loc.p8++ = (color >> 16) & 0xff;
			*loc.p8++ = (color >> 8) & 0xff;
			*loc.p8 = color & 0xff;
		}
		*loc.p8 |= transp_mask;
		break;
	case 4:
		if (xormode)
			*loc.p32 ^= color;
		else
			*loc.p32 = color;
		*loc.p32 |= transp_mask;
		break;
	}
}

void pixel(int32_t x, int32_t y, uint32_t colidx)
{
	uint32_t xormode;
	union multiptr loc;

	if ((x < 0) || ((uint32_t)x >= xres) ||
	    (y < 0) || ((uint32_t)y >= yres))
		return;

	xormode = colidx & XORMODE;
	colidx &= ~XORMODE;

	if (colidx > 255) {
#ifdef DEBUG
		fprintf(stderr, "WARNING: color value = %u, must be <256\n",
			colidx);
#endif
		return;
	}

	__pixel_loc(x, y, &loc);
	__setpixel(loc, xormode, colormap[colidx]);
}

void line(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t colidx)
{
	int32_t tmp;
	int32_t dx = x2 - x1;
	int32_t dy = y2 - y1;

	if (abs(dx) < abs(dy)) {
		if (y1 > y2) {
			tmp = x1; x1 = x2; x2 = tmp;
			tmp = y1; y1 = y2; y2 = tmp;
			dx = -dx; dy = -dy;
		}
		x1 <<= 16;
		/* dy is apriori >0 */
		dx = (dx << 16) / dy;
		while (y1 <= y2) {
			pixel(x1 >> 16, y1, colidx);
			x1 += dx;
			y1++;
		}
	} else {
		if (x1 > x2) {
			tmp = x1; x1 = x2; x2 = tmp;
			tmp = y1; y1 = y2; y2 = tmp;
			dx = -dx; dy = -dy;
		}
		y1 <<= 16;
		dy = dx ? (dy << 16) / dx : 0;
		while (x1 <= x2) {
			pixel(x1, y1 >> 16, colidx);
			y1 += dy;
			x1++;
		}
	}
}

void rect(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t colidx)
{
	line(x1, y1, x2, y1, colidx);
	line(x2, y1+1, x2, y2-1, colidx);
	line(x2, y2, x1, y2, colidx);
	line(x1, y2-1, x1, y1+1, colidx);
}

void fillrect(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t colidx)
{
	int32_t tmp;
	uint32_t xormode;
	union multiptr loc;

	/* Clipping and sanity checking */
	if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; }
	if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; }

	if (x1 < 0)
		x1 = 0;
	if ((uint32_t)x1 >= xres)
		x1 = xres - 1;

	if (x2 < 0)
		x2 = 0;
	if ((uint32_t)x2 >= xres)
		x2 = xres - 1;

	if (y1 < 0)
		y1 = 0;
	if ((uint32_t)y1 >= yres)
		y1 = yres - 1;

	if (y2 < 0)
		y2 = 0;
	if ((uint32_t)y2 >= yres)
		y2 = yres - 1;

	if ((x1 > x2) || (y1 > y2))
		return;

	xormode = colidx & XORMODE;
	colidx &= ~XORMODE;

	if (colidx > 255) {
#ifdef DEBUG
		fprintf(stderr, "WARNING: color value = %u, must be <256\n",
			colidx);
#endif
		return;
	}

	colidx = colormap[colidx];

	for (; y1 <= y2; y1++) {
		for (tmp = x1; tmp <= x2; tmp++) {
			__pixel_loc(tmp, y1, &loc);
			__setpixel(loc, xormode, colidx);
			loc.p8 += bytes_per_pixel;
		}
	}
}

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值