使用ts_calibrate校準觸摸屏

使用ts_lib包自帶的ts_calibrate校準觸摸屏非常簡單實用,但在基於Xsever的GUI應用環境下,有兩個問題存在:

  1.校準後必須重新啓動X,應用端才能生效。這樣處理用戶肯定不能接受,因爲啓動一次機器畢竟耗時。

  2.在使用ts_calibrate校準觸摸屏時,要觸摸5個點,這時如果GUI應用端在運行其他響應觸摸事件(鼠標事件)的程序就會出現錯亂。所以安全的做法應該是在校準觸摸屏時進行鎖屏操作。

  解決這兩個問題之前來看看tslib校準方面的原理,如果將原理搞清楚,剩下就是方法實現的問題了。

  Tslib 是觸摸屏驅動和應用層之間的適配層,它從觸摸屏驅動處獲得原始的設備座標數據,通過一系列的去噪、去抖、座標變換等操作,來去除噪聲並將原始的設備座標轉 換爲相應的屏幕座標。通過tslib/src/tslib.h文件可以看出,在tslib中爲應用層提供了2個主要的接口 ts_open(),ts_close();ts_read()和ts_read_raw(),其中ts_read()爲正常情況下的接 口,ts_read_raw()爲校準情況下使用的接口。從tslib默認的ts.conf文件中可以看出包括如下基本插件:

  pthres 爲Tslib 提供的觸摸屏靈敏度門檻插件;

  variance 爲Tslib提供的觸摸屏濾波算法插件;

  dejitter 爲Tslib 提供的觸摸屏去噪算法插件;

  linear爲Tslib 提供的觸摸屏座標變換插件。

  tslib 從觸摸屏驅動採樣到的設備座標進行處理再提供給應用端的過程大體如下:

  raw device --> variance --> dejitter --> linear --> application

  module         module       module      module

  再來看看ts_calibrate主要做了哪些事情,校準情況下,tslib對驅動採樣到的數據進行處理的一般過程如下:

  1。讀取屏上5個點的座標(Top Left,Top Right,Bottom Left,Bottom Right,Center),在進行一系列的變換,取樣的5個點,實際上是包含3個不同的X值,3個不同的Y值。和scaling 值一共7個值,一起保存到/etc/pointercal中.

  2.這個/etc/pointercal文件主要是供linear插件使用。而我們每次的觸摸的操作都進行多次觸摸座標變換。

  至此已經找到解決問題的大體的方法了。在校準觸摸屏後只需及時的讓linear插件再次讀取新的/etc/pointeracal文件,這樣新校準的座標信息就及時的更新到上層應用。下面就要考慮具體實現的問題了。

  1。從linear.c文件可以看出在該模塊初始化時讀取了/etc/pointercal文件。只要在linear_read()中讀取新的/etc/pointercal文件即可。

  2。校準後保存了一個新的pointercal文件,但ts_lib怎麼知道當前的pointercal文件是應該讀取的新文件。剛開始的時候 我們在 linear.c的linear_read()函數中採取計數輪詢的方式查看/etc/poinercal文件的最後更新時間,如果當前的更新時間大於上 次更新時間,就去讀取下pointercal文件。我們暫且不說在一臺剛下流水線的機器,它的rtc時間是不確定,再進行時間比較時會出現錯誤。另外始終 的輪詢的方式和ts_lib的採樣間隔時間值很小。這樣用戶在進行觸摸屏常按操作時,會非常明顯的消耗系統資源。

  3。此時想到的辦法就是進程通信,ts_lib是個動態庫運行於系統中,他存在系統中不是以進程方式,但可以採取折衷方法,將調用ts_lib 的進程號(實際上就是X的進程號)保存到一個配置文件中。這樣在使用ts_calibrate校準觸摸屏後,利用信號的方式給ts_lib發送用戶自定義 信號,ts_lib的 lineral.c中加一個簡單的信號處理函數。在接受到信號後就去讀取下新的pointercal文件。正常情況下不做任何的輪詢和讀取操作。

  從上說的3個步驟中完全解決了校準後應用端觸摸及時生效的問題。還有個次要問題就是如何鎖屏?這需要從內核入手了,查看linux 2.6內核 /drivers/input/evdev.c從該驅動提供的ioctl中看到對基於evdev的輸入設備都提供EVIOCGRAB實現。顧名思義,grab就是將當前的輸入操作抓取到當前的操作中,讓當前操作之外的所有應用端讀不到觸摸屏的觸摸操作。由驅動源碼 就很容易知道該如何實現鎖屏解鎖操作了。源碼 如下:

  truct tsdev *ts;

  char *tsdevice = "/dev/input/event0";

  ts = ts_open(tsdevice, 0);

  int ts_tmpfd = ts_fd(ts);

  if (ts_tmpfd== -1)

  {

  perror("ts_open");

  exit(1);

  }

  unsigned long val =1;

  int ioctl_ret=ioctl(ts_tmpfd,EVIOCGRAB,&val);

  printf("now lock the ts ioctl ret is:%dn",ioctl_ret);

  if (ioctl_ret!=0)

  {

  printf("Error: %sn", strerror(errno));

  exit(1);

  }

  printf("lock the ts success n");

 

 

  原文地址 http://blog.chinaunix.net/u3/94694/showart_1915009.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章