天天看点

让qt应用程序支持触摸

一.设备驱动

我的触摸屏是usb接口的

可以参考下这2篇文件

http://blog.csdn.net/paomadi/article/details/8754783 usb触摸屏

http://blog.csdn.net/paomadi/article/details/8309861 输入子系统

不是usb接口的或者自己想写多一个也可以(需要我的源码的请留邮箱说下,我贴一部分)

usb子系统部分关键在于urb的数据传递

input子系统部分关键在于事件的设置及上报

#define M //多点触摸点数
在初始化init或者probe方法中
input_dev=input_allocate_device();//分配初始化输入设备
//(最好构建一个对象结构体,包含input设备和usb设备,或其他设备,将各个子系统的设备捆绑到一个对象中去)

set_bit(EV_KEY, input_dev->evbit);	//设置事件类型标志位
set_bit(EV_ABS, input_dev->evbit);

set_bit(BTN_TOUCH, input_dev->keybit);	//设置按键类型标志

#if M
//多点的这么设置参数(我的屏只支持单点,so没亲测)
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,1920, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,1080, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
#else
//单点的参数设置
input_set_abs_params(input_dev, ABS_X, 0, 0x7FFF, 0, 0);	//设置参数
input_set_abs_params(input_dev, ABS_Y, 0, 0x7FFF, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
#endif
	
在接收到数据之后上报事件给input子系统
#if M
	//input_report_abs(touch->input, ABS_MT_TOUCH_MAJOR, 0);
	for(i=0;i<M;i++){
		input_report_abs(touchkit->input, ABS_MT_TRACKING_ID,0);
		input_report_key(touchkit->input, BTN_TOUCH, touchkit->press);
		input_report_abs(touchkit->input, ABS_MT_POSITION_X, touchkit->x);
		input_report_abs(touchkit->input, ABS_MT_POSITION_Y, touchkit->y);
		input_report_abs(touchkit->input, ABS_PRESSURE, touchkit->press);
		input_mt_sync(touchkit->input);	
	}
#else
	input_report_abs(input_dev, ABS_X, touchkit->x);
	input_report_abs(input_dev, ABS_Y, touchkit->y);
	input_report_key(input_dev, BTN_TOUCH,touchkit->press);
	input_report_abs(input_dev, ABS_PRESSURE, touchkit->press);
#endif
	input_sync(input_dev);
           

usb能匹配直接用hid子系统那是极好的

可以这样调试hid的设备
mkidr /tmp/debugfs
mount -t debugfs debugfs /tmp/debugfs
cd /tmp/debugfs
cd hid
cd 进对应的hid设备文件夹
cat event
           

其他的一些调试查看方法

ls -l /dev/input查看输入input设备

其中可以看到 lrwxrwxrwx    1 root     root            6 Jan  1  2000 touchscreen0 -> event1

/dev/input/touchscreen0是链接文件,链接到对应的触摸屏event1设备

查看event1是否触摸设备

cd /sys/class/input

cd event1

cd device

cat name

或者

cat /proc/bus/input/devices

比较Handlers和Name

cat /dev/input/touchscreen|hexdump 点击触摸屏查看接收到的数据

二.tslib

升级工具

sudo apt-get install autoconf

sudo apt-get install automake

sudo apt-get install libtool

解压tslib

tar xzf tslib-1.4.tar.gz

cd tslib

生产configure文件

./autogen.sh

创建安装目录

mkdir tmp

配置生成makefile文件

echo "ac_cv_func_malloc_0_nonnull=yes" >arm-none-linux-gnueabi.cache

./configure --host=arm-none-linux-gnueabi --cache-file=arm-none-linux-gnueabi.cache --prefix=$(pwd)/tmp

编译tslib

make

安装tslib

make install

安装完成后生成4个目录

/bin 目录包含ts_calibrate ts_test ts_harvest ts_print ts_print_raw测试执行文件

/etc 目录包含ts.conf配置文件

/include 目录包含 tslib.h头文件

/lib 目录包含 pkgconfig目录和ts目录和*.so(libts.so等)动态链接库

检验文件是否用交叉工具链编译的

file ts_calibrate查看打印的信息

文件系统配置

将/bin目录的和/etc目录下的文件复制到目标板文件系统的同样目录下

/include和/lib目录复制到目标板文件系统的/usr目录下

配置ts.conf

module_raw input

module pthres pmin=1

module variance delta=30

module dejitter delta=100

module linear

配置环境变量

打开目标板文件系统/etc/profile文件

export LD_LIBRARY_PATH=/usr/lib/    --库文件目录

export TSLIB_ROOT=/usr/       --tslib库文件/头文件根目录

export TSLIB_TSDEVICE=/dev/input/touchscreen0 --触摸屏设备文件路径

export TSLIB_CALIBFILE=/etc/pointercal   --校正文件路径 运行ts_calibrates会自动生成

export TSLIB_CONFFILE=/etc/ts.conf    --配置文件路径

export TSLIB_CONSOLEDEVICE=none     --

export TSLIB_FBDEVICE=/dev/fb0     --fb显示设备文件路径

export TSLIB_TSEVENTTYPE=INPUT     --触摸事件类型 input子系统

export TSLIB_PLUGINDIR=/usr/lib/ts    --

tslib测试

运行ts_calibrate

打印:

xres = 1920, yres = 1080

显示屏出现校正画面

点击方块(左上角)

打印:

Took 1 samples...

Top left : X =  752 Y = 1248

再次点击方块(右上角)

打印:

Took 2 samples...

Top right : X = 31938 Y = 1468

再次点击方块(右下角)

打印:

Took 2 samples...

Bot right : X = 31986 Y = 30926

再次点击方块(左下角)

打印:

Took 1 samples...

Bot left : X =  728 Y = 31278

再次点击方块(正中间)

打印:

Took 1 samples...

Center : X = 16387 Y = 16403

3.813721 0.058434 0.000070

3.860352 0.000071 0.032752

Calibration constants: 249936 3829 4 252992 4 2146 65536

校验完在/etc目录下生成/etc/pointercal

ts_calibrate可能会遇到一些问题

提示不是支持的触摸屏:查看TSLIB_TSDEVICE环境变量是否设置对

没点击方块就自动校正了:1.驱动BTN_TOUCH或者ABS_PRESSURE的值固化成1了(有上报按下事件没上报松开事件)

      2.库文件放错位置

运行ts_test

点击Drag按钮 可以拖动小方块

点击Draw按钮 可以在屏幕上画线

点击的时候会打印:xxx:[x坐标] [y坐标] [按下1/松开0]

1345221722.121520:   1920   1074      1

1345221722.121520:   1920   1074      1

1345221722.354517:   1920   1078      0

1345221724.035519:   1851    838      1

1345221724.045521:   1849    835      1

1345221724.065520:   1845    829      1

1345221724.081520:   1840    823      1

1345221724.091521:   1834    816      1

1345221724.104521:   1828    810      1

1345221724.121520:   1821    803      1

1345221724.137518:   1814    797      1

1345221724.153520:   1807    790      1

三.qt everywhere 4.8.1编译

重新配置tslib

/configure --host=arm-none-linux-gnueabi --cache-file=arm-none-linux-gnueabi.cache --prefix=/usr/local/tslib

修改安装目录

make

make install

修改qt-everywhere-opensource-src-4.8.1/mkspecs/qws/【xxx】/qmake.conf文件

QMAKE_CC = arm-none-linux-gnueabi-gcc -lts

QMAKE_CXX = arm-none-linux-gnueabi-g++ -lts

QMAKE_LINK = arm-none-linux-gnueabi-g++ -lts

QMAKE_LINK_SHLIB = arm-none-linux-gnueabi-g++ -lts

QMAKE_INCDIR =/usr/local/tslib/include

QMAKE_LIBDIR =/usr/local/tslib/lib

配置qt

.configure 后面加上 -no-mouse-linuxtp -qt-mouse-tslib

在test的过程中打印

Mouse driver(qt) ......pc tslib

表示库安装成功并成功检测到

编译qt

make

make install

example里面选择应用程序(推荐qt-everywhere-opensource-src-4.8.1/examples/widgets/calculator)

拷贝到目标板文件系统里

ldd calculator 查看calculator需要调用的库

打印:

libts-0.0.so.0 => /usr/lib/libts-0.0.so.0 (0x2ac3f000)
        libQtGui.so.4 => /usr/lib/libQtGui.so.4 (0x2ac49000)
        libQtNetwork.so.4 => /usr/lib/libQtNetwork.so.4 (0x2b6ae000)
        libQtCore.so.4 => /usr/lib/libQtCore.so.4 (0x2b7d6000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x2ab6a000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x2bb35000)
        libm.so.6 => /lib/libm.so.6 (0x2ab8a000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x2ab40000)
        libc.so.6 => /lib/libc.so.6 (0x2bc07000)
        libdl.so.2 => /lib/libdl.so.2 (0x2bd31000)
        librt.so.1 => /lib/librt.so.1 (0x2ab10000)
        /lib/ld-linux.so.3 (0x2aaea000)
           

看到libts-0.0.so.0说明tslib在qt中移植成功

ldd是个脚本,交叉工具链里面找

拷贝库文件到/usr/lib

在qt-everywhere-opensource-src-4.8.1/lib里面有la、prl、so和so.xxx文件

拷贝so和so.xxx文件就行

配置环境变量

打开目标板文件系统/etc/profile文件,添加以下

export LD_LIBRARY_PATH=/usr/lib/ ----库文件目录

export QWS_SIZE=1920x1080   ----分辨率

export QWS_MOUSE_PROTO="tslib:/dev/input/touchscreen0 mouseman:/dev/input/mouse0" ----"鼠标"类型

QWS_MOUSE_PROTO指定qt的鼠标,由【”】【第1个设备名字】【:】【设备文件路径】【空格】【第2个设备名字】【:】【设备文件路径】...【“】构成设备名字不区分大小写

设备名字可以是:(tslib、qnx、integrity、linuxtp、auto、intellimouse、microsoft、mousesystems、mouseman、linuxinput、usb、linuxis...)

该环境变量在qt源码qt-everywhere-opensource-src-4.8.1/src/gui/embedded/Qwindowsystem_qws.cpp的QWSServer::openMouse()函数中读取

QString mice=QString::fromLatin1(qgetenv("QWS_MOUSE_PROTO"))语句读入到mice,调试分析可以从这里入手

打印读取的环境变量:qDebug()<<mice,读取环境变量到mice后会判断mice中有多少个空格" ",也就是判断有多少个“鼠标”设备,个数作为后面for语句的循环因子,

for语句则调用QWSMouseHandler *handler=d->newMouseHandler(mouse.at(i))创建"鼠标"句柄,-->QMouseDriverFactory::create-->具体“鼠标”设备句柄的创建函数

QWSMouseHandler *QMouseDriverFactory::create(const QString& key, const QString &device)
{
    QString driver = key.toLower();
#if defined(Q_OS_QNX) && !defined(QT_NO_QWS_MOUSE_QNX)
    if (driver == QLatin1String("qnx") || driver.isEmpty())
        return new QQnxMouseHandler(key, device);
#endif
#if defined(Q_OS_INTEGRITY) && !defined(QT_NO_MOUSE_INTEGRITY)
    if (driver == QLatin1String("integrity") || driver.isEmpty())
        return new QIntMouseHandler(key, device);
#endif
#ifndef QT_NO_QWS_MOUSE_LINUXTP
    if (driver == QLatin1String("linuxtp") || driver.isEmpty())
        return new QWSLinuxTPMouseHandler(key, device);
#endif
#ifndef QT_NO_QWS_MOUSE_PC
    if (driver == QLatin1String("auto")
        || driver == QLatin1String("intellimouse")
        || driver == QLatin1String("microsoft")
        || driver == QLatin1String("mousesystems")
        || driver == QLatin1String("mouseman")
        || driver.isEmpty()) {
        return new QWSPcMouseHandler(key, device);					//mice...
    }
#endif
#ifndef QT_NO_QWS_MOUSE_TSLIB
    if (driver == QLatin1String("tslib") || driver.isEmpty())		//tslib
        return new QWSTslibMouseHandler(key, device);
#endif
# ifndef QT_NO_QWS_MOUSE_LINUXINPUT
    if (driver == QLatin1String("linuxinput") || \
        driver == QLatin1String("usb") || \
        driver == QLatin1String("linuxis"))
        return new QWSLinuxInputMouseHandler(device);
# endif
#ifndef QT_NO_QWS_MOUSE_QVFB
    if (driver == QLatin1String("qvfbmouse") || driver == QLatin1String("qvfb"))
        return new QVFbMouseHandler(key, device);
#endif

#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
#ifndef QT_NO_LIBRARY
    if (QWSMouseHandlerFactoryInterface *factory = qobject_cast<QWSMouseHandlerFactoryInterface*>(loader()->instance(driver)))
        return factory->create(driver, device);
#endif
#endif
    return 0;
}
           

如果鼠标类型没指定(mouseman之类的),则默认会调用/dev/input/mice这样会使你的触摸有点漂移的感觉,

这个情况很多人都碰到过,如果不需要鼠标 指定mouseman:/dev/NULL这样的话就没问题了。

凡是指定了鼠标设备的话都会引起触摸屏有点漂移的感觉.当你再触摸触摸屏时候,qt会读取你的触摸设备的数据和鼠标设备的数据

结果就是相对位移+绝对位移的处理结果,有点漂移,但还是勉强可以触摸.

还有一种情况会引起漂移现象,那就是你的环境变量没读取对,

也就是QWS_MOUSE_PROTO为空,所以最好添加qDebug()<<mice去调试一下,悲剧的是我就是碰到这种情况,即使用env查看是正确的也不一定说明你读取的环境变量是对的,你的应用程序

可能是在其他级别的用户或者在其他的bash环境下执行的,你的环境变量不一定对他起效.修改代码调试编译qt时候只需重新make一次,然后把前面说的库文件拷贝过去目标板就行了,

不费时间的

这里的QWS_MOUSE_PROTO的设置最好要写个shell脚本测试下是否插了鼠标,是否插了触摸屏根据判断的结果来不同的设置QWS_MOUSE_PROTO环境变量最好

查看你应用程序调用了那个input设备,使用lsof命令工具

lsof /dev/input/touchscreen0

打印:

COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME

xxxx 1771 root   41r   CHR  13,65      0t0 2326 /dev/input/event1

就是说xxxx打开了/dev/input/touchscreen0这个设备,这个设备是链接文件链接到/dev/input/event1

如果设备文件打开正确,但是触摸时候鼠标指针不动,运行一下ts_calibrate生成pointercal文件后再试试

这里可以添加下面shell脚本,在你打开qt应用程序前先判断是否校正过了,矫正过则执行qt程序,没校正过则校正一下

if [ ! -f "/etc/pointercal" ]; then 
	ts_calibrate
fi
           

 实现触摸屏+鼠标同时热拔插的方法:

1.export QWS_MOUSE_PROTO="tslib:/dev/input/touchscreen0 mouseman:/dev/input/mice"

触摸屏的设备节点可以是你自己的设备节点,鼠标的设备节点必须是mice

2设备节点随着热拔插不能发生变化

usb触摸屏,如果给hid子系统识别到,那可能受它框架束缚,热拔插节点会变化,我的方法是自己写usb触摸屏驱动,当然要先和hid子系统脱钩

在/driver/hid/hid-core.c文件中hid_bus_match函数中,添加了

static int hid_bus_match(struct device *dev, struct device_driver *drv)
{
	struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);

	if(hdev->vendor==0x1111){
		//printk("touch__________________________%s\n",__func__);	//touch
		return 0;	
	}
           

1111假设是我的触摸屏的厂商id,这样就匹配失败了

其次,自己写的usb触摸屏驱动随着热拔插设备节点也不能变化,那么...

我们知道input设备是虚拟的设备(没有硬件设备的),那么随着usb的插拔这个虚拟设备并不需要unregister,也就是说你usb_driver的disconnect方法中别input_unregister_device,释放在module_exit中释放

在usb_driver的probe方法中也别input_allocate_device和input_register_device这两个方法放在module_init的函数中

这样以input设备节点就不会变了,热拔插也没问题了

3.鼠标对触摸屏的影响

qt底层用QSocketNotifier监听着:/dev/input/touchscreen0和/dev/input/mice两个设备节点,一有数据可读就调用其connect指定的SLOT函数(qt的信号与槽)

tslib的:

int fd = ts_fd(dev);//获取设备的fd(/dev/input/touchscreen0)
    mouseNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);	//创建了QsocketNotifier监听fd
    connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));//调用readMouseData方法
           

读数据的函数void QWSTslibMouseHandlerPrivate::readMouseData()

鼠标的:

QSocketNotifier *mouseNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
    connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData(int)));
           

读数据的函数void QWSPcMouseHandlerPrivate::readMouseData(int fd)

添加点调试信息进去,发现每次点击触摸屏不仅会引起/dev/input/touchscreen0可读,而且会引起/dev/input/mice设备可读.移动鼠标的话就只有/dev/input/mice可读而已,

so问题必须是出现在/dev/input/mice设备相关的源码中,就是moousedev.c啦.

我干的活就是注释掉和绝对坐标相关的代码,如下:

static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
				unsigned int code, int value)
{
	int min, max, size;
#if 0 //MHB
	switch (code) {
	case ABS_X:
		min = input_abs_get_min(dev, ABS_X);
		max = input_abs_get_max(dev, ABS_X);
	
		size = max - min;
		if (size == 0)
			size = xres ? : 1;

		clamp(value, min, max);
		//printk("size=%d,xres=%d\n",size,xres);
		mousedev->packet.x = ((value - min) * xres) / size;
		mousedev->packet.abs_event = 1;
		break;

	case ABS_Y:
		min = input_abs_get_min(dev, ABS_Y);
		max = input_abs_get_max(dev, ABS_Y);

		size = max - min;
		if (size == 0)
			size = yres ? : 1;

		clamp(value, min, max);
		//printk("size=%d,yres=%d\n",size,yres);
		mousedev->packet.y = yres - ((value - min) * yres) / size;
		mousedev->packet.abs_event = 1;
		break;
	}
#endif
}
           

这样注释掉上报的ABS_X和ABS_Y事件对于/dev/input/mice来说等于给截断了,所以触摸的时候不会引起/dev/input/mice设备的可读,同时也不会影响相对位移事件对/dev/input/mice的通讯

由于mice这个节点是固定的,所以也支持热拔插

ok现在应该鼠标触摸屏都支持热拔插了,而且鼠标和触摸两个操作不会互相影响了。

补充最近的收获

由于硬件上的usb开关小板有点设计问题,切换usb的时候只是切换数据口,5v和gnd都没有切换,使得热拔插问题又不行了。

改成走hid路线,屏蔽usbtouchscreen.c的驱动-->匹配hid

(hid的代码参考MODULE_AUTHOR("Stephane Chatty <[email protected]>")的代码高版本内核中drivers/hid/hid-multitouch.c)

碰到问题1:

hid驱动识别出是多点的,走多点的驱动,而tslib是只支持单点的,所有出现"selected device is not a touchscreen I understand"

if (
			!(
				(ioctl(ts->fd, EVIOCGVERSION, &version) >= 0) && 
				(version == 0x010001) &&
				(ioctl(ts->fd, EVIOCGBIT(0, sizeof(bit) * 8), &bit) >= 0) &&
				(bit & (1 << EV_ABS)) &&
				(ioctl(ts->fd, EVIOCGBIT(EV_ABS, sizeof(absbit) * 8), &absbit) >= 0) &&
				(absbit & (1 << ABS_X)) &&
				(absbit & (1 << ABS_Y)) && 
				(absbit & (1 << ABS_PRESSURE))
			)
		) 
	{
		fprintf(stderr, "selected device is not a touchscreen I understand\n");
		return -1;
	}	
           

解决方法:

1.修改上报事件:多点改为单点

驱动中上报事件修改成ABS_X,ABS_Y..

for (i=0; i<td->num_expected; i++)
	{
		input_report_abs(input, ABS_MT_TOUCH_MAJOR, td->slots[i].valid);
		if (td->slots[i].valid)
		{
			input_report_abs(input, ABS_MT_TRACKING_ID, td->slots[i].id);
			input_report_abs(input, ABS_MT_POSITION_X, td->slots[i].x);
			input_report_abs(input, ABS_MT_POSITION_Y, td->slots[i].y);
		}
		input_mt_sync(input);
	}
           

改成

input_report_abs(input, ABS_X,td->slots[i].x);
	input_report_abs(input, ABS_Y, td->slots[i].y);
	input_report_abs(input, ABS_PRESSURE, td->slots[i].valid);	//按下?
           

2.修改input设备属性设置

在hidinput_connect函数中

if(hid->vendor==0xxxx){
					set_bit(EV_KEY, input_dev->evbit);
					set_bit(EV_ABS, input_dev->evbit);
					set_bit(BTN_TOUCH, input_dev->keybit);
					input_set_abs_params(input_dev, ABS_X, 0, 0x7FFF, 0, 0);
					input_set_abs_params(input_dev, ABS_Y, 0, 0x7FFF, 0, 0);
					input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
				}
				else{
					input_dev->setkeycode_new = hidinput_setkeycode;
					input_dev->getkeycode_new = hidinput_getkeycode;
				}
           

ok,这样hid就识别成单点的了,ts_lib就认设备了

注意:hidinput_connect是对所有hid设备都作用的,所以添加if(hid->vendor==0xxxx) xxxx为厂商ID这个是必须的,不然鼠标键盘等设备会变成触摸屏设备了。

问题2:热拔插

在hidinput_connect函数中可以看到input设备是动态分配的

hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
				input_dev = input_allocate_device();
           

虽然udev会识别触摸屏,并产生/dev/input/touchscreen0链接节点(/etc/udev/rules.d/local.rules文件中)

# Create a symlink to any touchscreen input device
SUBSYSTEM=="input", KERNEL=="event[0-9]*", SYSFS{modalias}=="input:*-e0*,3,*a0,1,*18,*", SYMLINK+="input/touchscreen0"
SUBSYSTEM=="input", KERNEL=="event[0-9]*", SYSFS{modalias}=="ads7846", SYMLINK+="input/touchscreen0"
           

但是对于tslib来说还是不能热拔插的(必须重启 ts_test或对应的qt程序)

所以需要按以前方法脱离usb设备和input设备,不好改

索性添加一个虚拟的input设备

在Stephane Chatty的程序中修改

先添加全局结构体

#define TOUCH 1

#if TOUCH
static struct input_dev *Vtouch;
#endif
           

module_init方法中添加

#if TOUCH
	Vtouch=input_allocate_device();	//输入设备内存分配->设置参数->注册	
	set_bit(EV_KEY, Vtouch->evbit);	
	set_bit(EV_ABS, Vtouch->evbit);	
	set_bit(BTN_TOUCH, Vtouch->keybit);	
	input_set_abs_params(Vtouch, ABS_X, 0, 0x7FFF, 0, 0);	
	input_set_abs_params(Vtouch, ABS_Y, 0, 0x7FFF, 0, 0);	
	input_set_abs_params(Vtouch, ABS_PRESSURE, 0, 1, 0, 0);	

	Vtouch->name = "Vtouch";	
	Vtouch->phys = "paomadi";	
	Vtouch->id.bustype = BUS_USB;	
	Vtouch->id.vendor = 0xxxx;	
	Vtouch->id.product = 0x0000;	
	Vtouch->id.version = 0x0000;	
	
	if(input_register_device(Vtouch))		
		printk("input_register_device error!\n");
#endif
           

注意这个Vtouch->name域,后面有大作用哦

在module_exit方法中添加

#if TOUCH	
	input_unregister_device(Vtouch);
#endif
           

在上报事件中来个很贱的招

input_report_abs(input, ABS_X,td->slots[i].x);
	input_report_abs(input, ABS_Y, td->slots[i].y);
	input_report_abs(input, ABS_PRESSURE, td->slots[i].valid);

	#if TOUCH	
		input_report_abs(Vtouch, ABS_X,td->slots[i].x);
		input_report_abs(Vtouch, ABS_Y, td->slots[i].y);
		input_report_abs(Vtouch, ABS_PRESSURE, td->slots[i].valid);
		input_sync(Vtouch);
	#endif
           

好,这样虚拟的input设备节点就固定了,不会随着usb拔插而改变

但是它可能是event0也可以是event1...关键看它啥时候给input_register_device了,这就有潜在的危险"万一不是event0呢!"

souceinsight搜索"event%d"

在/drivers/input/Evdev.c文件的evdev_connect函数中修改

if(dev->name=="Vtouch"){	// touch
	dev_set_name(&evdev->dev, "Vtouch");
}
else{
	dev_set_name(&evdev->dev, "event%d", minor);
}
           

编译内核更新到开发板,你会发现/dev/input下没有Vtouch

so ..修改udev规则/etc/udev/rules.d/udev.rules文件

#input devices分支下添加

KERNEL=="Vtouch” NAME="input/%k"

重启板子/dev/input/Vtouch文件就存在了

修改ts_lib的配置环境变量

export QWS_MOUSE_PROTO="tslib:/dev/input/Vtouch mouseman:/dev/input/mice"

export TSLIB_TSDEVICE="/dev/input/Vtouch"

ok全部搞定

继续阅读