Qt 5.x 相對於 4.8 及以前版本在窗口系統上有較大幅度改動,原來的 QWS 被 QPA 完全取代,導致輸入設備配置簡化了很多,執行界面程序也不需要再加上-qws
。
找到觸摸屏event
用的 USB 接口驅動觸摸屏,當你插入 usb 的電容屏時,在 dev/input 下面會出現相應的設備節點。假如cat /dev/event0
,觸摸屏幕有亂碼輸出,則說明 usb 觸摸屏驅動產生中斷並且將采集數據上報 input 子系統了。
另外也可以使用 hexdump 命令,它是 Linux 下的一個二進制文件查看工具,它可以將二進制文件轉換為 ASCII、八進制、十進制、十六進制格式進行查看,默認顯示十六進制格式,使用 -d 命令參數顯示十進制,詳細使用參考:Linux命令學習總結:hexdump
使用 hexdump 命令查看觸摸信息,快速觸摸屏幕右下角后的打印信息如下:
$ hexdump -d /dev/input/event0
0000000 15989 00000 18969 00004 00004 00004 00001 00009 # 其它事件
0000010 15989 00000 18969 00004 00001 00272 00001 00000 # BTN_MOUSE,按下
0000020 15989 00000 18969 00004 00003 00000 16333 00000 # ABS_X
0000030 15989 00000 18969 00004 00003 00001 09599 00000 # ABS_Y
0000040 15989 00000 18969 00004 00000 00000 00000 00000 # 同步事件
0000050 15989 00000 49415 00005 00004 00004 00001 00009 # 其它事件
0000060 15989 00000 49415 00005 00001 00272 00000 00000 # BTN_MOUSE,松開
0000070 15989 00000 49415 00005 00000 00000 00000 00000 # 同步事件
倒數第四、三、二行分別為 type、code 和 value,在 linux/input.h 都有定義,Linux 中輸入設備的事件類型有:
#define EV_SYN 0x00 // 同步事件
#define EV_KEY 0x01 // 按鍵事件
#define EV_REL 0x02 // 相對坐標
#define EV_ABS 0x03 // 絕對坐標
#define EV_MSC 0x04 // 其它事件
-
type 是事件類型,為 3 就是 EV_ABS=0x03,為 0 就是 EV_SYN=0x00(作為事件的分隔)。
-
code 的話根據事件類型而定,如果是 type 為 EV_ABS,code 為 0 就是 ABS_X,code 為 1 就是 ABS_Y。
-
然后 value 就是在 type 和 code 的前提下的值,比如 type 為 EV_ABS,code 為 0 就是 ABS_X,那么 value 就代表觸摸點的 x 軸絕對值。
-
比如 type 為 EV_KEY,code 為 272 就是 BTN_MOUSE,code 為 330 就是 BTN_TOUCH,那么 value 為 1 表示按下,為 0 表示松開。比如 type 為 EV_ABS,code 為 24 就是 ABS_PRESSURE,value 為 1 表示按下,為 0 表示松開。
測試看出觸摸屏觸摸產生的坐標值范圍為 X:016384,Y:09600,同時該觸摸屏沒有上傳 ABS_PRESSURE。
通過 cat /proc/bus/input/devices 應該就能夠看到觸摸設備的相關信息。比如:
$ cat /proc/bus/input/devices
I: Bus=0003 Vendor=222a Product=0001 Version=0110
N: Name="ILITEK ILITEK-TP"
P: Phys=usb-11000000.xhci-1.4/input1
S: Sysfs=/devices/soc/11000000.xhci/usb1/1-1/1-1.4/1-1.4:1.1/0003:222A:0001.0004/input/input2
U: Uniq=
H: Handlers=mouse0 js0 event0
B: PROP=0
B: EV=1b
B: KEY=1f0000 0 0 0 0 0 0 0 0
B: ABS=3
B: MSC=10
上面的信息有觸摸屏 vid,pid,版本等,以及 ABS 表示觸摸屏的絕對坐標掩碼,掩碼上面表示 16 進制,所以 3=0x0000003=0000 0000 0000 0000 0000 0000 0011,其中為 1 的比特的位置就表示觸摸屏會報告這一類型的事件,前面的 bit0 和 bit1,那么看 linux/input.h 文件就表示事件 code 碼有 ABS_X=0x00 , ABS_Y=0x01, 這兩個分別表示觸摸屏報告觸摸的 x 坐標,y 坐標。而 bit24 為 0,則表示觸摸屏驅動沒有上傳 ABS_PRESSURE。詳情請參考:linux讀取觸摸屏事件數據
Qt使用電容屏
使用電容屏的 Qt 程序,不用移植 tslib 庫,就可以直接讀取輸入設備文件(/etc/input/eventx),除非需要 tslib 校准。另外 Qt4 默認支持觸屏,而 Qt5 需要設置環境變量才能支持觸屏:
export QT_LOGGING_RULES=qt.qpa.input=true # 打印觸屏信息
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0 # 指定輸入設備的名稱
export QT_QPA_EVDEV_MOUSE_PARAMETERS=/dev/input/event0 # 將觸摸屏的點擊事件配置成Qt的鼠標點擊事件
export QT_QPA_FB_HIDECURSOR=1 # 為1則隱藏鼠標光標,為0則顯示鼠標光標
- 對於 Qt5,設置環境變量
QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS
,Qt5 自身的 libinput 就會去/dev/input/eventX
讀取觸摸屏數據(未校准),從而使觸摸正常工作。 - 將觸摸屏的點擊事件配置成 Qt 的鼠標點擊事件后,會產生有一個鼠標光標。
電容屏的校准
觸摸屏配置可分兩種方式,一種是電容屏或由驅動校准的電阻屏配置,另一種是需要借助 tslib 校准的電阻屏配置。
所以電容屏本身是不需要校准的,不過和 Qt 配合的話就需要重新校准:
一、Qt 本身提供了一個校准軟件,叫做 mousecalibration,不過只能支持 Embedded Linux(嵌入式 Linux),軟件在 example->qws 目錄下面,可以完成校准。但是由於不同的嵌入式平台采用的芯片差異性很大,所以這個校准程序往往無法使用。其詳細說明參考:Mouse Calibration Example
二、使用 tslib校准:帶 tslib 校准的方式需要移植最新版 tslib 庫,再編譯 Qt 源碼或插件(Qt 自帶的插件可以單獨編譯,自帶插件不支持多點觸摸),編譯時加入 tslib 到編譯選項。移植到嵌入式設備后,配置 tslib 校准服務開機啟動,之后配置 Qt 宏默認使用 tslib 插件作為默認輸入插件。
1、校准原理說明
分辨率轉化和校准
其實觸摸屏觸摸產生的坐標值是絕對坐標,范圍為 X:016384,Y:09600。所以,我們運行的 Qt 程序如果直接獲取 /dev/input/eventx 產生的坐標的話,鼠標位置便會超出屏幕的顯示范圍(1920*1080),因此,我們需要進行一下坐標值轉化。
參考:
linux內核usb觸摸屏驅動bug調試- selected device is not a touchscreen I understand