? ? 大家好,我是ST。
? ? 今天主要和大家聊一聊,如何使用tslib庫來完成對應的功能。
第一:tslib庫基本簡介
? ? 上篇文章為了獲取觸摸點,主要是對讀取到的struct input_event類型數據進行分析,得到各個觸摸點坐標。接下來,主要使用tslib庫進行學習,這是Linux系統下,專門為觸摸屏開發的應用層函數庫。
? ? ?tslib庫是開源的,也就是可以直接獲取到tslib的源代碼。tslib為觸摸屏驅動和應用層之間的適配層,它把應用程序中讀取觸摸屏struct input_event類型數據(這是輸入設備上報給應用層的原始數據)并進行解析的操作過程進行了封裝,向使用者提供了封裝好的API接口。tslib從觸摸屏中獲得原始的坐標數據,并通過一系列的去抖、坐標變換等操作,來去除噪聲并將原始的觸摸屏坐標轉換為相應的屏幕坐標。
? ? tslib可以作為Qt的觸摸屏輸入插件,為Qt提供觸摸輸入支持,如果在嵌入式Linux硬件平臺上開發過Qt應用程序應該知道,并不是只有 tslib 才能作為 Qt 的插件、為其提供觸摸輸入支持,還有很多插件都可以。
第二:tslib安裝目錄下的文件夾介紹
? ? ?進入到tslib安裝目錄下:
? ? ?bin目錄
? ? ?bin目錄下有一些tslib提供的小工具,可以用于測試觸摸屏,如下所示:
? ? ?etc目錄
? ? ?etc目錄下有一個配置文件ts.conf,前面給大家提到過:
? ???打開ts.conf文件看看它有哪些配置選項:
? ? ? module_raw input:取消注釋,使能支持input輸入事件;
module pthres pmin=1:如果我們的設備支持按壓力大小測試,那么可以把它的注釋取消,pmin 用于調節按壓力靈敏度,默認就是等于 1。
module dejitter delta=100:tslib 提供了觸摸屏去噪算法插件,如果需要過濾噪聲樣本,取消注釋,默認參數 delta=100。
module linear:tslib 提供了觸摸屏坐標變換的功能,譬如將 X、Y 坐標互換、坐標旋轉等之類,如果我們需要實現坐標變換,可以把注釋去掉。
這里就不去改動了,直接使用默認的配置就行了。
? ? ?include?目錄
? ? ?include目錄下只有一個頭文件tslib.h,該頭文件中包含了一些結構體數據結構以及API接口的聲明,使用tslib提供的API就需要包含該頭文件。
? ? ?lib目錄
? ? ?lib目錄下包含了編譯tslib源碼所得到的庫文件,默認這些都是動態庫文件,也可以通過配置tslib工程使其生成靜態庫文件;ts目錄下存放的是一些插件庫。
第三:在開發板上測試tslib庫
? ? ??使用tslib提供的API接口來編寫觸摸屏的應用程序,使用tslib庫函數需要在我們的應用程序中包含tslib的頭文件tslib.h,使用tslib編程其實非常簡單,基本步驟如下所示:
? ? ?? 第一步打開觸摸屏設備;
?? ? ? 第二步配置觸摸屏設備;
? ? ? ?第三步讀取觸摸屏數據;
?1、打開觸摸屏設備
? ? ??使用tslib提供的庫函數ts_open打開觸摸屏設備,其函數原型如下所示:
?
#include "tslib.h" struct?tsdev?*ts_open(const?char?*dev_name,int?nonblock);
?
? ? ? 參數dev_name 指定了觸摸屏的設備節點;參數nonblock表示是否以非阻塞方式打開觸摸屏設備,如果nonblock等于0表示阻塞方式,如果為非0值則表示以非阻塞方式打開。
? ? ??調用成功返回一個struct sdev *指針,指向觸摸屏設備句柄;如果打開設備失敗,將返回NULL。除了使用ts_open()打開設備外,還可以使用ts_setup()函數,其函數原型如下所示:
?
#inlcude "tslib.h"
?
? ?參數 dev_name 指定觸摸屏的設備節點,與 ts_open()函數中的 dev_name 參數意義相同;但對于 ts_setup()來說,參數 dev_name 可以設置為 NULL,當 dev_name 設置為 NULL 時,ts_setup()函數內部會讀取TSLIB_TSDEVICE 環境變量,獲取該環境變量的內容以得知觸摸屏的設備節點。
? ? ?ts_setup()相比ts_open(),除了打開觸摸屏設備外,還可以對觸摸屏設備進行配置。
2、配置觸摸屏設備
? ? ?調用ts_config()函數進行配置,其函數原型如下所示:
?
#include?"tslib.h" int ts_config(struct tsdev *ts)
?
? ? ?參數ts指向觸摸屏句柄。
? ? ?成功返回0,失敗返回-1。
? ? ?所謂配置其實指的就是解析ts.conf文件中的配置信息,加載相應的插件。
第四:讀取觸摸屏數據
? ? ?讀取觸摸屏數據使用 ts_read()或 ts_read_mt()函數,區別在于 ts_read 用于讀取單點觸摸數據,而ts_read_mt 則用于讀取多點觸摸數據,其函數原型如下所示:
?
#include "tslib.h" int ts_read(struct tsdev *ts,struct ts_sample *samp,int nr) int ts_read_mt(struct tsdev *ts, struct ts_sample_mt **samp, int max_slots, int nr)
?
? ? ? 參數ts指向一個觸摸屏設備句柄,參數nr表示對一個觸摸點的采樣數,設置為1即可。
? ? ? ts_read_mt()函數有一個 max_slots 參數,表示觸摸屏支持的最大觸摸點數,應用程序可以通過調用 ioctl()函數來獲取觸摸屏支持的最大觸摸點數以及觸摸屏坐標的最大分辨率等信息,稍后向大家介紹。
? ? ? ts_read()函數的 samp 參數是一個 struct ts_sample *類型的指針,指向一個 struct ts_sample 對象,struct ts_sample 數據結構描述了觸摸點的信息;調用 ts_read()函數獲取到的數據會存放在 samp 指針所指向的內存中。struct ts_sample 結構體內容如下所示:
?
struct ts_sample{ int x; //X坐標 int y; //Y坐標 unsigned int pressure; //按壓力大小 ?????struct timeval tv; //時間 };
?
? ? ? ts_read_mt()函數的 samp 參數是一個 struct ts_sample_mt **類型的指針,多點觸摸應用程序,每一個觸摸點的信息使用 struct ts_sample_mt 數據結構來描述;一個觸摸點的數據使用一個 struct ts_sample_mt 對象來裝載,將它們組織成一個 struct ts_sample_mt 數組,調用 ts_read_mt()時,將數組地址賦值給 samp 參數。
? ? ?struct ts_sample結構體內容如下所示:
?
struct ts_sample_mt { /* ABS_MT_* event codes. linux/include/uapi/linux/input-event-codes.h * has the definitions. */ int x; //X 坐標 int y; //Y 坐標 unsigned int pressure; //按壓力大小 int slot; //觸摸點 slot int tracking_id; //ID int tool_type; int tool_x; int tool_y; unsigned int touch_major; unsigned int width_major; unsigned int touch_minor; unsigned int width_minor; int orientation; int distance; int blob_id; struct timeval tv; //時間 /* BTN_TOUCH state */ short pen_down; //BTN_TOUCH 的狀態 ?short?valid;??//此次樣本是否有效標志 ?};
?
第五:單點觸摸應用程序實現
?
#include#include #include? ????//包含tslib.h的頭文件 int main(int argc, char *argv[]) { struct tsdev *ts = NULL; struct ts_sample samp; int pressure = 0;//用于保存上一次的按壓力,初始為 0,表示松開 /* 打開并配置觸摸屏設備 */ ts = ts_setup(NULL, 0); if (NULL == ts) { fprintf(stderr, "ts_setup error"); exit(EXIT_FAILURE); } /* 讀數據 */ for ( ; ; ) { if (0 > ts_read(ts, &samp, 1)) { fprintf(stderr, "ts_read error"); ts_close(ts); exit(EXIT_FAILURE); } if (samp.pressure) {//按壓力>0 if (pressure) //若上一次的按壓力>0 ?????printf("移動(%d,%d) ",samp.x,samp.y); ?????else ?????printf("按下(%d,%d) ",samp.x,samp.y); ?????} ?????else printf("松開 ");//打印坐標 pressure = samp.pressure; } ts_close(ts); exit(EXIT_SUCCESS); }
?
分析:利用代碼直接打開、配置設備、接著讀取數據,通過判斷按壓大小確定觸摸的狀態。
?
${CC} -I /home/dt/tools/tslib/include -L /home/dt/tools/tslib/lib -lts -o testApp testApp.c
?
? ??-I選項指定頭文件的路徑,也就是指定tslib安裝目錄下的include目錄,如果不指定頭文件路徑,編譯時將會找不到tslib.h頭文件;-L 選項用于指定庫文件的路徑,也就是指定 tslib 安裝目錄下的 lib 目錄;我們將 tslib 編譯成了動態庫文件,以庫文件的形式提供,編譯時需要鏈接到這些庫文件;而-l 選項則用于指定鏈接庫(也可寫成-l ts,也就是 libts.so 庫文件,Linux 中,動態庫文件的命名方式為 lib+名字+.so)。
? ? ? 將編譯得到的可執行文件拷貝到開發板 Linux 系統的用戶家目錄下,執行應用程序,進行測試:
第六:多點觸摸應用程序實現
? ??接下來基于tslib的多點觸摸應用程序,使用ts_read_mt()函數讀取多點觸摸數據。
?
#include#include #include #include #include int main(int argc, char *argv[]) { struct tsdev *ts = NULL; struct ts_sample_mt *mt_ptr = NULL; struct input_absinfo slot; int max_slots; unsigned int pressure[12] = {0}; //用于保存每一個觸摸點上一次的按壓力,初始為 0,表示松開 int i; /* 打開并配置觸摸屏設備 */ ts = ts_setup(NULL, 0); if (NULL == ts) { fprintf(stderr, "ts_setup error"); exit(EXIT_FAILURE); } /* 獲取觸摸屏支持的最大觸摸點數 */ if (0 > ioctl(ts_fd(ts), EVIOCGABS(ABS_MT_SLOT), &slot)) { perror("ioctl error"); ts_close(ts); exit(EXIT_FAILURE); } max_slots = slot.maximum + 1 - slot.minimum; printf("max_slots: %d ", max_slots); /* 內存分配 */ mt_ptr = calloc(max_slots, sizeof(struct ts_sample_mt)); /* 讀數據 */ for ( ; ; ) { if (0 > ts_read_mt(ts, &mt_ptr, max_slots, 1)) { perror("ts_read_mt error"); ts_close(ts); free(mt_ptr); exit(EXIT_FAILURE); } for (i = 0; i < max_slots; i++) { if (mt_ptr[i].valid) {//有效表示有更新! if (mt_ptr[i].pressure) { //如果按壓力>0 if (pressure[mt_ptr[i].slot])//如果上一次的按壓力>0 printf("slot<%d>, 移動(%d, %d) ", mt_ptr[i].slot, mt_ptr[i].x, mt_ptr[i].y); else printf("slot<%d>, 按下(%d, %d) ", mt_ptr[i].slot, mt_ptr[i].x, mt_ptr[i].y); } else printf("slot<%d>, 松開 ", mt_ptr[i].slot); pressure[mt_ptr[i].slot] = mt_ptr[i].pressure; } } } /* 關閉設備、釋放內存、退出 */ ts_close(ts); free(mt_ptr); exit(EXIT_SUCCESS); }
?
? ??? 整個思路與單點觸摸應用程序相同,通過ts_read_mt()函數讀取觸摸點數據,將這些數據存放在 mt_ptr 數組中,接著在 for()循環中判斷每一個觸摸點數據是否有效,有效則表示該觸摸點信息發生更新。
?
${CC} -I /home/dt/tools/tslib/include -L /home/dt/tools/tslib/lib -lts -o testApp testApp.c
?
?將編譯得到的可執行文件復制到開發板Linux系統用戶家目錄下,執行程序:
總結:觸摸屏在很多場合下都會使用到,掌握tslib庫的使用方法,對未來個人的開發具有重要作用。
審核編輯:湯梓紅
評論
查看更多