天天看點

讓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全部搞定

繼續閱讀