Re: touchscreen wirh 2.6.26

From: TamÃsi JÃnos
Date: Wed Dec 09 2009 - 16:29:32 EST


Hi!

I wrote a small (and really ugly) uinput driver to this device. I hope this helps somebody to write a proper driver for this touchscreen.


2009-11-28 00:30 keltezÃssel, Jiri Kosina Ãrta:
On Fri, 27 Nov 2009, Alex Custov wrote:

Bus 004 Device 002: ID 0408:3000 Quanta Computer, Inc.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0408 Quanta Computer, Inc.
idProduct 0x3000
Unfortunately, this touchscreen is not (yet) neither supported by
usbtouchscreen kernel driver, nor is it apparently HID standard compliant,
so HID driver can't do much with it as well.

You will have to reverse-engineer the data protocol the touchscreen is
sending. It's usually quite easy, in cases in which the device doesn't
require complex initialization before it can become functional.


// uinput.c
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
/*
* Globals
*/
static int uinp_fd = -1;
struct uinput_user_dev uinp; // uInput device structure
struct input_event event; // Input device structure

/*
* Setup the uinput device
*/
int setup_uinput_device() {
// Temporary variable
int i = 0;

// Open the input device
uinp_fd = open("/dev/input/uinput", O_WRONLY | O_NDELAY);
if (&uinp_fd == NULL) {
printf("Unable to open /dev/input/uinput\n");
return -1;
}
memset(&uinp, 0, sizeof(uinp)); // Intialize the uInput device to NULL
strncpy(uinp.name, "Acer T230H", UINPUT_MAX_NAME_SIZE);
uinp.id.version = 4;
uinp.id.bustype = BUS_USB;
uinp.absmax[ABS_X] = 1920+1440; // i have another monitor connected;
uinp.absmin[ABS_X] = 0;
uinp.absfuzz[ABS_X] = 3;
uinp.absmin[ABS_X] = 0;

uinp.absmax[ABS_Y] = 1080;
uinp.absmin[ABS_Y] = 0;
uinp.absfuzz[ABS_Y] = 3;
uinp.absmin[ABS_Y] = 0;

// Setup the uinput device
ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
ioctl(uinp_fd, UI_SET_EVBIT, EV_ABS);
ioctl(uinp_fd, UI_SET_ABSBIT, ABS_X);
ioctl(uinp_fd, UI_SET_ABSBIT, ABS_Y);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_LEFT);

/*
* Create input device into input sub-system
*/
write(uinp_fd, &uinp, sizeof(uinp));
if (ioctl(uinp_fd, UI_DEV_CREATE)) {
printf("Unable to create UINPUT device.\n");
return -1;
}
return 1;
}

void pukk() {
int fd;
unsigned int x,
y,
xx,
yy;
unsigned char buf[30];

fd = open("/dev/hidraw6", O_RDONLY);
while (1) {
read(fd, buf, sizeof(buf));
x = buf[4] + (unsigned int) buf[5] * 256;
y = buf[6] + (unsigned int) buf[7] * 256;
xx = buf[10] + (unsigned int) buf[11] * 256;
yy = buf[12] + (unsigned int) buf[13] * 256;

// set x & y
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
event.type = EV_ABS;
event.code = ABS_X;
event.value = x + 1440; // a have another monitor connected :)
write(uinp_fd, &event, sizeof(event));
event.type = EV_ABS;
event.code = ABS_Y;
event.value = y;
write(uinp_fd, &event, sizeof(event));
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(uinp_fd, &event, sizeof(event));

if (buf[2] == 7) { // BTN1 pressed
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
event.type = EV_KEY;
event.code = BTN_LEFT;
event.value = 1;
write(uinp_fd, &event, sizeof(event));
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(uinp_fd, &event, sizeof(event));
}

if (buf[2] == 4) { // BTN1 released
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
event.type = EV_KEY;
event.code = BTN_LEFT;
event.value = 0;
write(uinp_fd, &event, sizeof(event));
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(uinp_fd, &event, sizeof(event));
}

printf("\n%ux%u %ux%u [%u]\n", x, y, xx, yy, buf[2]);
}
close(fd);
}

int main() {
// Return an error if device not found.
if (setup_uinput_device() < 0) {
printf("Unable to find uinput device\n");
return -1;
}
pukk();
ioctl(uinp_fd, UI_DEV_DESTROY);
close(uinp_fd);
return 0;
}