linux内核关闭触摸屏校准,linux内核usb触摸屏驱动bug调试- selected device is not a touchscreen I understand...
近期給客戶調試一塊數控板,今天客戶帶過來一個屏,并且有一個usb的觸摸屏芯片接在屏上。屏很快就弄好正常顯示。
觸摸屏在內核下找到usb 觸摸屏驅動,內核啟動后這個usb轉的觸摸屏也正常找到,注冊為event接口事件event0, cat /dev/event0,觸摸屏幕有亂碼輸出,說明usb觸摸屏驅動產生中斷并且將采集數據上報input子系統了。
然后用我移植的tslib中有幾個校準測試程序,運行,發現出現下面的錯誤:
selected device is not a touchscreen I understand
屏上出現校準界面,但是校準的5個點瞬間連了一遍程序就出錯結束了。
多次嘗試都是這個結果,我就插入一個usb的鼠標,識別產生event1,我就講為tslib運行設置的環境變量中tslib的設備設為event1,再運行校準程序,發現現象跟觸摸屏的一樣。也就說tslib中應該是有容錯處理,會先根據一些條件來判斷這個環境變量指定的設備是否是一個真正的觸摸屏設備。
想多無意,還是多看代碼,于是在tslib源碼中找到上面這句的出處如下:
static int check_fd(struct tslib_input *i)
{
struct tsdev *ts = i->module.dev;
int version;
u_int32_t bit;
u_int64_t absbit;
if (! ((ioctl(ts->fd, EVIOCGVERSION, &version) >= 0) &&
(version == EV_VERSION) &&
(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;
}
if (bit & (1 << EV_SYN))
i->using_syn = 1;
return 0;
}
這個check_fd中會根據這些條件來判斷是否打印如上錯誤。
第一個條件是ioctl獲取version,內核源碼下找到ioctl定義在driver/input/evdev.c中,對應命令EVIOCGVERSION定義值為0x10000 而編譯器中input.h中定義值也是0x10000,這個條件沒有問題。我看網上關于這個錯誤大部分問題都是處在這里。可惜我的不是,繼續往下。
第二個條件是獲取input設備的bit標志,也就是看這個是被是否是一個觸摸屏設備。usb設備我之前也沒有接觸過,但是根據cat /dev/event0,有反應,說明usb部分采集數據是沒有問題的,只是上報給input子系統出了問題,所以應該想到的是看一下usb觸摸屏驅動注冊input設備的部分代碼,在usb觸摸屏驅動driver/usb/input/usbtouchscreen.c中的probe函數中代碼如下:
input_dev->name = usbtouch->name;
input_dev->phys = usbtouch->phys;
usb_to_input_id(udev, &input_dev->id);
input_dev->cdev.dev = &intf->dev;
input_dev->private = usbtouch;
input_dev->open = usbtouch_open;
input_dev->close = usbtouch_close;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0);
input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0);
if (type->max_press)
input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press,
type->max_press, 0, 0);
可以看到evbit中設置了EV_ABS標志位。這樣第二個條件也滿足了。
第三個條件是獲取專為觸摸屏input設備準備的absbit標志中是否有觸摸屏對應的標志位,因為之前寫過一個觸摸屏驅動,所以知道觸摸屏標志位為x y press,也就是坐標以及按壓。
在input_set_abs_params實現中是為absbit置各種標志位。并且設置對應標志的范圍(min max),但是這個標志比如x y press的范圍在后面沒有看到使用,我也實驗發現min max都寫0也沒有問題,這個是題外話了。
這里就出現了問題了,usb觸摸屏中枚舉出來的設備中max_press和min_press都沒有設置,為0,所以最后這個設置press標志位的函數就沒有調用。
所以我上面出現selected device is not a touchscreen I understand 是因為? absbit & (1 << ABS_PRESSURE)不滿足造成的!
我把if判斷注釋掉,然后重編內核啟動,運行tslib測試程序,發現不會出現上面的錯誤退出了,這個問題算是解決。后來我實驗發現input_set_abs_params中設置x y press的min max都沒有用到,即使這些都設置為0也沒有影響。
校準測試程序正常算是運行,但是我點擊屏幕,校準程序并沒有檢測到我的點擊行為,接著就遇到了這個問題。接著研究搞定!
運行tslib測試程序沒有檢測到點擊事件,但是cat /dev/event0時點擊屏幕是有東西傳給input子系統的,這說明觸摸屏中斷是正常的。
之間編寫另外一個觸摸屏驅動的時候點擊事件上報坐標數據給input子系統是在觸摸屏的中斷中做的,因此需要找到這段代碼來看一下有沒有問題,在usbtouchscreen.c中找到如下代碼:
static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
unsigned char *pkt, int len)
{
struct usbtouch_device_info *type = usbtouch->type;
if (!type->read_data(usbtouch, pkt))
return;
input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch);
if (swap_xy) {
input_report_abs(usbtouch->input, ABS_X, usbtouch->y);
input_report_abs(usbtouch->input, ABS_Y, usbtouch->x);
} else {
input_report_abs(usbtouch->input, ABS_X, usbtouch->x);
input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);
}
if (type->max_press)
input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
input_sync(usbtouch->input);
}
這段代碼是中斷中上報數據給input子系統的部分,report key是標志輸入事件是否按下和彈起,而對于觸摸屏來說上報的數據包括x y press,這段代碼中可以看出由于max_press為0,所以中斷中一直沒有上報press,也就是說usb觸摸屏一直上報的是坐標,但是press值一直為0,所以上層程序就會認為沒有按壓下去。所以沒有反應。在中斷中加打印,發現從usb讀出來的數據press值為0,不管是按下還是彈起,但是touch在按下的時候是1,彈起的時候是0,可以用這個值來上報給input子系統當前的press,函數修改如下:
static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
unsigned char *pkt, int len)
{
struct usbtouch_device_info *type = usbtouch->type;
if (!type->read_data(usbtouch, pkt))
return;
input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch);
//zk modify for usb touchpad
input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->touch);
if (swap_xy) {
input_report_abs(usbtouch->input, ABS_X, usbtouch->y);
input_report_abs(usbtouch->input, ABS_Y, usbtouch->x);
} else {
input_report_abs(usbtouch->input, ABS_X, usbtouch->x);
input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);
}
#if 0
if (type->max_press)
input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
#endif
input_sync(usbtouch->input);
}
重新編譯內核,啟動,運行tslib的校準測試程序,可以正常點擊,并且tslib程序可以檢測到觸摸屏數據了!成功!!
總結
以上是生活随笔為你收集整理的linux内核关闭触摸屏校准,linux内核usb触摸屏驱动bug调试- selected device is not a touchscreen I understand...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux maven .m2文件夹,M
- 下一篇: linux脚本多个条件比较大小,如何在s