構(gòu)體詳解)
4.4 觸控屏應(yīng)用接口4.4.1 輸入子系統(tǒng)簡介連接操作系統(tǒng)的輸入設(shè)備可不止一種也許是一個(gè)標(biāo)準(zhǔn) PS/2 鍵盤也許是一個(gè) USB鼠標(biāo)或者是一塊觸摸屏甚至是一個(gè)游戲機(jī)搖桿 Linux 在處理這些紛繁各異的輸入設(shè)備的時(shí)候采用的辦法還是找中間層來屏蔽各種細(xì)節(jié)請看下圖在 Linux 的內(nèi)核中對輸入設(shè)備的使用實(shí)際上運(yùn)用了 3 大塊來管理他們分別是所謂的輸入設(shè)備驅(qū)動層、輸入子系統(tǒng)核心層以及事件觸發(fā)層。他們各自的工作分別是1輸入設(shè)備驅(qū)動層每一種設(shè)備都有其特定的 驅(qū)動程序 他們被妥當(dāng)?shù)匮b載到操作系統(tǒng)的設(shè)備模型框架內(nèi)封裝硬件所提供的功能向上提供規(guī)定的接口。2核心層此處將收集由設(shè)備驅(qū)動層發(fā)來的數(shù)據(jù)整合之后觸發(fā)某一事件。3事件觸發(fā)層這一層是我們需要關(guān)注的我們可以通過在用戶空間讀取相應(yīng)設(shè)備的節(jié)點(diǎn)文件來獲知某設(shè)備的某一個(gè)動作。在最靠近應(yīng)用程序的事件觸發(fā)層上內(nèi)核所獲知的各類輸入事件比如鍵盤被按了一下觸摸屏被滑了一下等都將被統(tǒng)一封裝在一個(gè)叫做 input_event 的結(jié)構(gòu)體當(dāng)中這個(gè)結(jié)構(gòu)體定義如下(/usr/inlucde/linux/input.h) vincentubuntu:/usr/inlucde/linux/$ cat input.h -n 1 #ifndef _INPUT_H 2 #define _INPUT_H 3…… 20 21 struct input_event { 22 struct timeval time; 23 __u16 type; 24 __u16 code; 25 __s32 value; 26 }; 27……該結(jié)構(gòu)體有 4 個(gè)成員其含義分別如下一、time輸入事件發(fā)生的時(shí)間戳精確到微秒。時(shí)間結(jié)構(gòu)體定義如下struct timeval { __time_t tv_sec; // 秒 long int tv_usec; // 微秒1 微秒 10-3毫秒 10-6秒 };二、type輸入事件的類型。比如EV_SYN事件間的分割標(biāo)志有些事件可能會在時(shí)間和空間上產(chǎn)生延續(xù)比如持續(xù)按住一個(gè)按鍵。為了更好地管理這些持續(xù)的事件EV_SYN 用以將他們分割成一個(gè)個(gè)的小的數(shù)據(jù)包。EV_KEY用以描述鍵盤按鍵或者類似鍵盤的設(shè)備的狀態(tài)變化。EV_REL相對位移比如鼠標(biāo)的移動滾輪的轉(zhuǎn)動等。EV_ABS絕對位移比如觸摸屏上的坐標(biāo)值。EV_MSC不能匹配現(xiàn)有的類型這相當(dāng)于當(dāng)前暫不識別的事件。比如在 Linux系統(tǒng)中按下鍵盤中針對 Windows 系統(tǒng)的“一鍵殺毒”按鍵將會產(chǎn)生該事件。EV_LED用于控制設(shè)備上的 LED 燈的開關(guān)比如按下鍵盤的大寫鎖定鍵會同時(shí)產(chǎn)生 ”EV_KEY” 和 ”EV_LED” 兩個(gè)事件。三、code這個(gè)“事件的代碼”用于對事件的類型作進(jìn)一步的描述。比如當(dāng)發(fā)生 EV_KEY事件時(shí)則可能是鍵盤被按下了那么究竟是哪個(gè)按鍵被按下了呢此時(shí)查看 code 就知道了。當(dāng)發(fā)生 EV_REL 事件時(shí)也許是鼠標(biāo)動了也許是滾輪動了。這時(shí)可以用 code 的值來加以區(qū)分。四、value當(dāng) code 都不足以區(qū)分事件的性質(zhì)的時(shí)候可以用 value 來確認(rèn)。比如由EV_REL 和 REL_WHEEL 確認(rèn)發(fā)生了鼠標(biāo)滾輪的動作但是究竟是向上滾還是向下滾呢再比如由由 EV_KEY 和 KEY_F 確認(rèn)了發(fā)生鍵盤上 F 鍵的動作但究竟是按下呢還是彈起呢這時(shí)都可以用 value 值來進(jìn)一步判斷。以下代碼展示了如何從觸摸屏設(shè)備節(jié)點(diǎn)/dev/event0 中讀取數(shù)據(jù)并顯示當(dāng)前觸摸屏的實(shí)時(shí)原始數(shù)據(jù)vincentubuntu:~/ch04/4.5$ cat ts_raw.c - 1 #include stdio.h 2 #include stdlib.h 3 #include stdbool.h 4 #include unistd.h 5 #include string.h 6 #include strings.h 7 #include errno.h 8 9 #include sys/stat.h 10 #include sys/types.h 11 #include fcntl.h 12 #include Linux/input.h 13 14 int main(int argc, char **argv) 15 { 16 int ts open(/dev/event0, O_RDONLY); 17 18 struct input_event buf; 19 bzero(buf, sizeof(buf)); 20 21 while(1) 22 { 23 read(ts, buf, sizeof(buf)); 24 25 switch(buf.type) 26 { 27 case EV_SYN: 28 printf(--------------------- SYN ------------------\n); 29 break; 30 case EV_ABS: 31 printf(time: %u.%u\ttype: EV_ABS\t, 32 buf.time.tv_sec, buf.time.tv_usec); 33 switch(buf.code) 34 { 35 case ABS_X: 36 printf(X:%u\n, buf.value); 37 break; 38 case ABS_Y: 39 printf(Y:%u\n, buf.value); 40 break; 41 case ABS_PRESSURE: 42 printf(pressure:%u\n, buf.value); 43 } 44 } 45 } 46 return 0; 47 }c運(yùn)行注意以上代碼打印出來的是直接從觸摸屏讀取的原始數(shù)據(jù)raw data沒有經(jīng)過任何校正也沒有任何濾波、去抖、消噪因此這些數(shù)據(jù)是不能直接給應(yīng)用層程序使用的但是不用擔(dān)心這些繁瑣復(fù)雜的工作已經(jīng)有了很成熟的庫支持了但是有一個(gè)TSLIB 庫就是這樣一個(gè)開源的、能為觸摸屏獲得的原始數(shù)據(jù)提供諸如濾波、去抖、消噪和校正功能的庫TSLIB 作為觸摸屏驅(qū)動的適配層為上層的應(yīng)用提供了一個(gè)統(tǒng)一的編程接口將使得我們編寫基于觸摸屏的應(yīng)用更加簡便。Linux下struct input_event結(jié)構(gòu)體詳解_怎么使用粵嵌開發(fā)板觸摸屏幕-CSDN博客