usb触摸屏驱动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程序可以检测到触摸屏数据了!成功!!

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 内核中,添加触摸屏驱动需要在内核配置文件(kconfig)中进行定义。以下是示例代码: ``` config TOUCHSCREEN_MYDRIVER tristate "My Touchscreen Driver" depends on I2C && INPUT help Say Y here if you want to enable support for My Touchscreen Driver. This driver supports a touch controller connected via I2C. If unsure, say N. config TOUCHSCREEN_MYDRIVER_I2C_ADDR hex "I2C address of the touch controller" default 0x48 depends on TOUCHSCREEN_MYDRIVER help Enter the I2C address of the touch controller chip. The default value is 0x48. config TOUCHSCREEN_MYDRIVER_MAX_POINTS int "Maximum number of simultaneous touch points" default 5 depends on TOUCHSCREEN_MYDRIVER help Enter the maximum number of simultaneous touch points that the touch controller can handle. The default value is 5. ``` 在上面的示例代码中,我们定义了一个名为 `TOUCHSCREEN_MYDRIVER` 的触摸屏驱动。该驱动使用 I2C 总线连接到触摸屏控制器,并依赖于 `INPUT` 和 `I2C` 子系统。我们还定义了两个配置选项: - `TOUCHSCREEN_MYDRIVER_I2C_ADDR`:这个选项用于设置触摸屏控制器的 I2C 地址。默认值为 0x48。 - `TOUCHSCREEN_MYDRIVER_MAX_POINTS`:这个选项用于设置触摸屏控制器支持的最大触摸点数。默认值为 5。 当用户编译 Linux 内核时,可以使用 `make menuconfig` 命令进入内核配置界面,找到 `Device Drivers -> Input device support -> Touchscreens` 选项,然后选择要启用的触摸屏驱动。用户还可以在该界面中设置 `TOUCHSCREEN_MYDRIVER_I2C_ADDR` 和 `TOUCHSCREEN_MYDRIVER_MAX_POINTS` 配置选项的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值