linux USB触屏无响应驱动出现EPIPE错误

版权声明:转载请注明出处。 https://blog.csdn.net/yangyang031213/article/details/84133160

#linux触屏无响应驱动出现EPIPE错误
使用的触屏设备是egalax通过USB接入的,使用的驱动是 kernel\linux-3.10.y\drivers\input\touchscreen\usbtouchscreen.c。出现问题时触屏没有反应,hexdump /dev/input/event0也没有输出,但是重启QT程序后正常。问题很难复现,复现后也获取不到多少有用信息,后来直接将触屏USB输入输出线短路复现此问题。后续发现触屏无反应时出现EPIPE错误:

static void usbtouch_irq(struct urb *urb)
{
 struct usbtouch_usb *usbtouch = urb->context;
 struct device *dev = &usbtouch->interface->dev;
 int retval;

 switch (urb->status) {
 case 0:
  /* success */
  break;
 case -ETIME:
  /* this urb is timing out */
  dev_dbg(dev,
   "%s - urb timed out - was the device unplugged?\n",
   __func__);
  return;
 case -ECONNRESET:
 case -ENOENT:
 case -ESHUTDOWN:
 case -EPIPE:
  /* this urb is terminated, clean up */
  dev_dbg(dev, "%s - urb shutting down with status: %d\n",
   __func__, urb->status);
  return;
 default:
  dev_dbg(dev, "%s - nonzero urb status received: %d\n",
   __func__, urb->status);
  goto exit;
 }

 usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length);

exit:
 usb_mark_last_busy(interface_to_usbdev(usbtouch->interface));
 retval = usb_submit_urb(urb, GFP_ATOMIC);
 if (retval)
  dev_err(dev, "%s - usb_submit_urb failed with result: %d\n",
   __func__, retval);
}

添加一些打印后发现,结束QT程序后,再打开QT程序,驱动会重新open设备。没有找到比较好的办法,于是在驱动层出现EPIPE错误的时候,向上层上报一个特殊值,应用层监控/dev/input/event0,检测到特殊值时,重启QT程序,修改usbtouchscreen.c如下:

static void usbtouch_irq(struct urb *urb)
{
 struct usbtouch_usb *usbtouch = urb->context;
 struct device *dev = &usbtouch->interface->dev;
 int retval;

    dev_err(&usbtouch->interface->dev,"XXXXXXXX file:%s func:%s IN status:%d",__FILE__,__func__,urb->status);
 switch (urb->status) {
 case 0:
  /* success */
  break;
 case -ETIME:
  /* this urb is timing out */
  dev_dbg(dev,
   "%s - urb timed out - was the device unplugged?\n",
   __func__);
  return;
 case -ECONNRESET:
 case -ENOENT:
 case -ESHUTDOWN:
  /* this urb is terminated, clean up */
  dev_dbg(dev, "%s - urb shutting down with status: %d\n",
   __func__, urb->status);
  return;
 case -EPIPE://出现EPIPE错误,上报一个特殊值
     dev_err(&usbtouch->interface->dev,"XXXXXXXXXXXXXXXXXXXXXXXXX EPIPE ERROR file:%s func:%s EPIPE status:%d",__FILE__,__func__,urb->status);
  usbtouch->touch = 1;
  usbtouch->x = 20480;
  usbtouch->y = 20480;
  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);
  }
  input_sync(usbtouch->input);
  goto exit;
 default:
  dev_dbg(dev, "%s - nonzero urb status received: %d\n",
   __func__, urb->status);
  goto exit;
 }
 usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length);
exit:
 usb_mark_last_busy(interface_to_usbdev(usbtouch->interface));
 retval = usb_submit_urb(urb, GFP_ATOMIC);
 if (retval)
  dev_err(dev, "%s - usb_submit_urb failed with result: %d\n",
   __func__, retval);
}

监控程序:

#include <stdio.h>
#include <linux/input.h>
#include <fcntl.h>
#include <sys/time.h>
#include <unistd.h>

bool openFile(int & fdTouch){
    fdTouch = open("/dev/input/event0", O_RDWR);
    if(fdTouch <= 0){
        printf("Can not /dev/input/event0\n");
        return false;
    }
    printf("Open /dev/input/event0 success\n");
    return true;
}

int main(int argc, char **argv)
{
    int fdTouch = -1;
    char buf[128] = {0};
    while(1) {
        if(fdTouch <= 0){
            openFile(fdTouch);
        }
        if(fdTouch > 0){
            int len = read(fdTouch, buf, sizeof(buf));
            if (len > 0){
                for(int pos = 0;len >= pos + 16;pos += 16){
                    //hexdump /dev/input/event0    出现EPIPE错误时上报的特殊值
                    //2be9 5ba7 a6d4 0005 0003 0000 5000 0000
                    //2be9 5ba7 a6d4 0005 0003 0001 5000 0000
                    if(3 == buf[pos + 8] && 0 == buf[pos + 9] && (0 == buf[pos + 10] || 1 == buf[pos + 10]) && 0 == buf[pos + 11] && 0 == buf[pos + 12] && 80 == buf[pos + 13] && 0 == buf[pos + 14] && 0 == buf[pos + 15]){
                        printf("Read driver define value ,need kill ui and client.\n");
                        close(fdTouch);
                        fdTouch = -1;
                        sleep(2);
                        printf("Close fdTouch in read driver define value\n");
                        int loop = 0;
                        while (true) {
                            openFile(fdTouch);
                            if(fdTouch > 0){    //等到能正常打开/dev/input/event0时重启QT程序
                                printf("Retry open /dev/input/event0 SUCCESS close fdTouch times:%d\n",loop);
                                close(fdTouch);
                                fdTouch = -1;
                                sleep(1);
                                break;
                            }
                            fdTouch = -1;
                            ++loop;
                            printf("Retry open /dev/input/event0 times:%d\n",loop);
                            usleep(500 * 1000);
                        }
                        system("killall -kill qtPrograme");//杀死QT程序,进程监控程序会重启它的
                        break;
                    }
                }
            }
            else if(len < 0){
                close(fdTouch);
                fdTouch = -1;
                printf("Close fdTouch \n");
            }
        }
        usleep(200 * 1000);
    }
    close(fdTouch);
    return 0;
}

目前测试未在出现问题。

猜你喜欢

转载自blog.csdn.net/yangyang031213/article/details/84133160