飞凌原厂内核移植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;
}
}
}