Калибровка и настройка evdevtouch во встроенном проекте qt
У меня есть проект Qt, работающий на icoremx6solo с Linux. Я настроил графику и запустил код, но я не могу обрабатывать сенсорный ввод. Включение регистрации входа с
export QT_LOGGING_RULES="qt.qpa.input=true"
я обнаружил, что координаты не установлены, я думаю, что это главная проблема с этим:
qt.qpa.input: evdevtouch: /dev/input/event0: Protocol type B (multi)
qt.qpa.input: evdevtouch: /dev/input/event0: min X: 0 max X: -1
qt.qpa.input: evdevtouch: /dev/input/event0: min Y: 0 max Y: -1
qt.qpa.input: evdevtouch: /dev/input/event0: min pressure: 0 max pressure: 0
qt.qpa.input: evdevtouch: /dev/input/event0: device name: EP0790M09
но я не могу найти способ откалибровать это evdevtouch.
Я попытался запустить исполняемый файл с атрибутом -plugin tslib после выполнения команды ts_calibrate, но вывод остался прежним.
Итак, как я могу это исправить, имея работающий сенсорный экран?
2 ответа
Спасибо ianeman! Из вашего ответа мне удалось заставить мой 5-дюймовый сенсорный экран xpt2046 работать с Qt. Мой код:
#include "setuptouchscreen.h"
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>
#include <string.h>
#include <dirent.h>
#include <qdebug.h>
#define DEVICE_NAME "ADS7846 Touchscreen"
#define INPUT_PATH "/dev/input"
// got these values from file https://github.com/goodtft/LCD-show/blob/master/usr/99-calibration.conf-5-0
#define X_MIN 140
#define X_MAX 3951
#define Y_MIN 261
#define Y_MAX 3998
int setupTouchScreen() {
DIR* directory = opendir(INPUT_PATH);
if (!directory) {
qDebug("setupTouchScreen:: Failed to open %s.", INPUT_PATH);
return -1;
}
bool found = false;
struct dirent *entry = NULL;
while (!found && (entry = readdir(directory))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char pathname[NAME_MAX + 1]; /* should always be big enough */
sprintf( pathname, "%s/%s", INPUT_PATH, entry->d_name );
qDebug("setupTouchScreen:: Path name: %s", entry->d_name);
int fd = open(pathname, O_RDONLY);
if (fd == NULL) {
puts ("setupTouchScreen:: Could not open device file - are you running as root");
}
else
{
char name[256] = "Unknown";
ioctl (fd, EVIOCGNAME(sizeof(name)), name);
qDebug("setupTouchScreen:: Input device name: %s", name);
if(strcmp(name, DEVICE_NAME ) != 0 ) {
qDebug("setupTouchScreen:: This is not the event file of the touchscreen: %s. Value is: %s", DEVICE_NAME, name);
} else {
qDebug("setupTouchScreen:: Found input file!");
found = true;
struct input_absinfo absval;
// Read the ioctl and display the current values
qDebug("setupTouchScreen:: Writing event struct ABS_X");
ioctl(fd, EVIOCGABS(ABS_X), &absval);
// check if a write is wanted - and do it
absval.minimum = X_MIN;
absval.maximum = X_MAX;
ioctl(fd, EVIOCSABS(ABS_X), &absval);
/////////////////
qDebug("setupTouchScreen:: Writing event struct ABS_Y");
ioctl(fd, EVIOCGABS(ABS_Y), &absval);
absval.minimum = Y_MIN;
absval.maximum = Y_MAX;
ioctl(fd, EVIOCSABS(ABS_Y), &absval);
}
}
close(fd);
}
closedir(directory);
if(!found)
{
qDebug("setupTouchScreen:: Could not find device file for device %s", DEVICE_NAME);
return -1;
}
qDebug("setupTouchScreen:: Success!");
return 0;
}
Глядя на источник QT (qevdevtouchhandler.cpp), значения калибровки (мин, макс, давление...) получены непосредственно с устройства ioctl.
Кажется, в Qt нет способа изменить эти значения.
Глядя на исходный код ядра для моего контроллера (ADS7843 на Atmel spi), кажется, нет способа изменить значения из пользовательского пространства (/proc, /sys).
Следующий фрагмент, кажется, делает работу - чтение и запись значений калибровки:
// check the parameter count
if (argc != 3 && argc != 5) {
puts ("Get usage: evgetset device absnumber");
puts ("Set usage: evgetset device absnumber valname value");
return (1);
}
// the first parameter is the device file name
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
puts ("Could not open device file - are you running as root");
return (1);
}
// the second parameter is the parameter number
absnumber = atoi (argv[2]);
if (absnumber < 0 || absnumber > ABS_MAX) {
puts ("absnumber out of range");
return (1);
}
// Read the ioctl and display the current values
ioctl(fd, EVIOCGABS(absnumber), &absval);
printf ("Properties for %d\n", absnumber);
printf ("Value : %d\n", absval.value);
printf ("Minimum : %d\n", absval.minimum);
printf ("Maximum : %d\n", absval.maximum);
printf ("Fuzz : %d\n", absval.fuzz);
printf ("Flat : %d\n", absval.flat);
// printf ("Resolution : %d\n", absval.resolution);
// check if a write is wanted - and do it
if (argc == 5) {
valvalue = atoi (argv[4]);
if (!strcmp ("Value", argv[3])) absval.value = valvalue;
if (!strcmp ("Minimum", argv[3])) absval.minimum = valvalue;
if (!strcmp ("Maximum", argv[3])) puts ("Got Maximum");
if (!strcmp ("Maximum", argv[3])) absval.maximum = valvalue;
if (!strcmp ("Fuzz", argv[3])) absval.fuzz = valvalue;
if (!strcmp ("Flat", argv[3])) absval.flat = valvalue;
// if (!strcmp ("Resolution", argv[2]) absval.resolution = valvalue;
ioctl(fd, EVIOCSABS(absnumber), &absval);
}
// all done
close(fd);