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

35 篇文章 1 订阅

#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;
}

目前测试未在出现问题。

Linux错误码65280对应的错误号(errno)是126,表示执行一个命令时发生了错误。以下是常见的Linux错误号及其对应的错误: 1. EPERM (1):操作不允许 2. ENOENT (2):文件或目录不存在 3. ESRCH (3):没有这样的进程 4. EINTR (4):系统调用被中断 5. EIO (5):输入/输出错误 6. ENXIO (6):没有这样的设备或地址 7. E2BIG (7):参数列表太长 8. ENOEXEC (8):执行格式错误 9. EBADF (9):文件描述符无效 10. ECHILD (10):没有这样的子进程 11. EAGAIN (11):资源暂时不可用 12. ENOMEM (12):内存不足 13. EACCES (13):权限不足 14. EFAULT (14):错误的地址 15. ENOTBLK (15):块设备必须使用块IO 16. EBUSY (16):设备或资源忙 17. EEXIST (17):文件已存在 18. EXDEV (18):跨文件系统链接 19. ENODEV (19):操作不支持设备 20. ENOTDIR (20):不是目录 21. EISDIR (21):是目录 22. EINVAL (22):无效的参数 23. ENFILE (23):文件打开太多 24. EMFILE (24):文件描述符打开太多 25. ENOTTY (25):不是终端设备 26. ETXTBSY (26):文本文件忙 27. EFBIG (27):文件太大 28. ENOSPC (28):没有空间 29. ESPIPE (29):无效的seek 30. EROFS (30):只读文件系统 31. EMLINK (31):链接太多 32. EPIPE (32):捕获信号管道 33. EDOM (33):数学参数超出定义域 34. ERANGE (34):数学结果不可表示 35. EDEADLK (35):资源死锁避免 36. ENAMETOOLONG (36):文件名太长 37. ENOLCK (37):没有可用的记录锁 38. ENOSYS (38):函数不支持 39. ENOTEMPTY (39):目录不为空 40. ELOOP (40):太多的符号链接 41. ENOMSG (42):没有消息的标识符 42. EIDRM (43):标识符已删除 43. ECHRNG (44):通道范围不正确 44. EL2NSYNC (45):Level 2不同步 45. EL3HLT (46):Level 3被挂起 46. EL3RST (47):Level 3重置 47. ELNRNG (48):Link number超出范围 48. EUNATCH (49):Protocol driver不可用 49. ENOCSI (50):没有CSI结构可用 50. EL2HLT (51):Level 2被挂起 51. EBADE (52):无效的交换 52. EBADR (53):无效的请求描述符 53. EXFULL (54):交换空间已满 54. ENOANO (55):没有对应的自动识别对象 55. EBADRQC (56):无效的请求描述符或参数 56. EBADSLT (57):Slot不存在 57. EBFONT (59):无效字体文件格式 58. ENOSTR (60):设备不是流 59. ENODATA (61):没有数据可用 60. ETIME (62):计时器已过期 61. ENOSR (63):没有记录可用 62. ENONET (64):网络不可用 63. ENOPKG (65):包没有安装 64. EREMOTE (66):对象是远程的 65. ENOLINK (67):链路不存在 66. EADV (68):广告错误 67. ESRMNT (69):Srmount错误 68. ECOMM (70):通信错误 69. EPROTO (71):协议错误 70. EMULTIHOP (72):多跳跃I / O 71. EDOTDOT (73):RFS特定错误 72. EBADMSG (74):错误的消息 73. EOVERFLOW (75):值太大以便于定义 74. ENOTUNIQ (76):名称不唯一 75. EBADFD (77):文件描述符在错误状态 76. EREMCHG (78):远程地址已更改 77. ELIBACC (79):无法访问共享库 78. ELIBBAD (80):共享库损坏 79. ELIBSCN (81):没有共享库文本段 80. ELIBMAX (82):共享库表已满 81. ELIBEXEC (83):无法执行共享库 82. EILSEQ (84):无效的或不完整的多字节序列 83. ERESTART (85):无需重新启动系统调用 84. ESTRPIPE (86):管道流不支持 85. EUSERS (87):太多用户 86. ENOTSOCK (88):套接字操作的目标不是套接字 87. EDESTADDRREQ (89):需要目标地址 88. EMSGSIZE (90):消息太长 89. EPROTOTYPE (91):错误的协议类型 90. ENOPROTOOPT (92):协议不可用 91. EPROTONOSUPPORT (93):协议不支持 92. ESOCKTNOSUPPORT (94):套接字类型不支持 93. EOPNOTSUPP (95):操作不支持 94. EPFNOSUPPORT (96):协议族不支持 95. EAFNOSUPPORT (97):地址族不支持 96. EADDRINUSE (98):地址已在使用中 97. EADDRNOTAVAIL (99):不能分配所需的地址 98. ENETDOWN (100):网络已关闭 99. ENETUNREACH (101):网络不可达 100. ENETRESET (102):网络连接已重置 101. ECONNABORTED (103):连接被中止 102. ECONNRESET (104):连接被重置 103. ENOBUFS (105):没有缓冲区可用 104. EISCONN (106):套接字已连接 105. ENOTCONN (107):套接字未连接 106. ESHUTDOWN (108):不能执行发送,套接字已关闭 107. ETOOMANYREFS (109):太多参考:无法分配请求的资源 108. ETIMEDOUT (110):连接超时 109. ECONNREFUSED (111):连接被拒绝 110. EHOSTDOWN (112):主机已关闭 111. EHOSTUNREACH (113):主机不可达 112. EALREADY (114):操作已经在进行中 113. EINPROGRESS (115):操作正在进行中 114. ESTALE (116):Stale NFS文件句柄 115. EUCLEAN (117):结构取消 116. ENOTNAM (118):不是XENIX命名文件 117. ENAVAIL (119):No XENIX semaphores available 118. EISNAM (120):Is a named type file 119. EREMOTEIO (121):远程I / O错误 120. EDQUOT (122):Quota exceeded 121. ENOMEDIUM (123):没有中介信息 122. EMEDIUMTYPE (124):中介错误 123. ECANCELED (125):操作被取消 124. ENOKEY (126):没有KEY值 125. EKEYEXPIRED (127):KEY已过期 126. EKEYREVOKED (128):KEY已被撤销 127. EKEYREJECTED (129):KEY被拒绝 128. EOWNERDEAD (130):所有者已死 129. ENOTRECOVERABLE (131):无法恢复
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值