USB触摸屏的驱动

2023-11-07

  我们都知道410c没有配套的触摸屏,如果有屏的话,在调试或者其他方面就方便多了,所以我们自己买了一个usb触摸屏,现在让我们看看usb触摸屏的驱动。

  驱动路经:drivers/input/touchscreen/usbtouchscreen.c


  (1)设备匹配

    module_usb_driver(usbtouch_driver);

   static struct usb_driver usbtouch_driver = {
          .name       = "usbtouchscreen",
   ..............
          .id_table   = usbtouch_devices,
            .............
     };


static const struct usb_device_id usbtouch_devices[] = {
    12 #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
    13     /* ignore the HID capable devices, handled by usbhid */
    14     {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE},
    15     {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE},
    16
    17     /* normal device IDs */
    18     {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
    19     {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
    20     {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
    21     {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
    22     {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
    23     {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX},
    24     {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX},
    25 #endif
    26
    27 #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
    28     {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT},
    29     {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT},
    30     {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT},
    31     {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT},
    32 #endif
    33
 ......................

 }

 添加的支持的设备,其中(0x3823, 0x0001)分别为usb设备的厂商id(vid)和产品id(pid),DEVTYPE_EGALAX则在下面定义

    24 enum {
    25     DEVTYPE_IGNORE = -1,
    26     DEVTYPE_EGALAX,
    27     DEVTYPE_PANJIT,
    28     DEVTYPE_3M,
    29     DEVTYPE_ITM,
    30     DEVTYPE_ETURBO,
    31     DEVTYPE_GUNZE,
    32     DEVTYPE_DMC_TSC10,
    33     DEVTYPE_IRTOUCH,
    34     DEVTYPE_IDEALTEK,
    35     DEVTYPE_GENERAL_TOUCH,
    36     DEVTYPE_GOTOP,
    37     DEVTYPE_JASTEC,
    38     DEVTYPE_E2I,
    39     DEVTYPE_ZYTRONIC,
    40     DEVTYPE_TC45USB,
    41     DEVTYPE_NEXIO,
    42     DEVTYPE_ELO,
    43     DEVTYPE_ETOUCH,
    44 };

一旦这些都有了,设备匹配成功就会执行probe函数


  (2)



struct usb_device *udev = interface_to_usbdev(intf):获取接口对应的设备

usbtouch_get_input_endpoint:获取端点描述符指针。

input_allocate_device:申请输入设备对象内存

type = &usbtouch_dev_info[id->driver_info]:根据driver_info获取全局usbtouch_dev_info的数组项。

usbtouch_process_pkt用于中断回调函数,上传数据到应用层

usb_alloc_coherent:分配内存

usb_alloc_urb申请用于urb用于数据传输的内存,注意:这里将返回“usbtouch->data”

usbtouch->data记录了用于普通传输用的内存指针
usbtouch->buffer记录了用于存储读取到的数据的内存指针

usb_make_path填充设备结构体中的节点名。用来获取 USB 设备在 Sysfs 中的路径

usb_autopm_get_interface:电源唤醒

usb_submit_urb:提交urb

usb_autopm_put_interface:关闭电源

 

 主要来看一下usbtouch_dev_info

 1074 static struct usbtouch_device_info usbtouch_dev_info[] = {                                                                                                                                            
     1 #ifdef CONFIG_TOUCHSCREEN_USB_ELO
     2     [DEVTYPE_ELO] = {
     3         .min_xc     = 0x0,
     4         .max_xc     = 0x0fff,
     5         .min_yc     = 0x0,
     6         .max_yc     = 0x0fff,
     7         .max_press  = 0xff,
     8         .rept_size  = 8,
     9         .read_data  = elo_read_data,
    10     },
    11 #endif
    12
    13 #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
    14     [DEVTYPE_EGALAX] = {
    15         .min_xc     = 0x0,
    16         .max_xc     = 0x07ff,
    17         .min_yc     = 0x0,
    18         .max_yc     = 0x07ff,
    19         .rept_size  = 16,
    20         .process_pkt    = usbtouch_process_multi,
    21         .get_pkt_len    = egalax_get_pkt_len,
    22         .read_data  = egalax_read_data,
    23         .init       = egalax_init,
    24     },
    25 #endif

 ............................

 }

   

以DEVTYPE_EGALAX为例:

egalax_init:初始化设备

  48 static int egalax_init(struct usbtouch_usb *usbtouch)
    47 {
    46     int ret, i;
    45     unsigned char *buf;
    44     struct usb_device *udev = interface_to_usbdev(usbtouch->interface);

   //interface_to_usbdev:根据usb_interface指针intf获取usb_device的地址。
    
    32     buf[0] = EGALAX_PKT_TYPE_DIAG;
    31     buf[1] = 1; /* length */
    30     buf[2] = 'A';   /* command - check active */
    29
    28     for (i = 0; i < 3; i++) {
    27         ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
    26                       0,
    25                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
    24                       0, 0, buf, 3,
    23                       USB_CTRL_SET_TIMEOUT);
 

  //usb_control_msg:是没有用到urb的在USB中简单进行发送和接收的一种机制,用于少量的数据通信。

    11 }


egalax_get_pkt_len:获取包的长度

 357  static int egalax_get_pkt_len(unsigned char *buf, int len)                                                                                                                                            
     1 {
     2     switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
     3     case EGALAX_PKT_TYPE_REPT:
     4         return 5;
     5
     6     case EGALAX_PKT_TYPE_DIAG:
     7         if (len < 2)
     8             return -1;
     9
    10         return buf[1] + 2;
    11     }
    12
    13     return 0;
    14 }


egalax_read_data:用于中断回调函数,用于读取数据

  345  static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt)                                                                                                                             
     1 {
     2     if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
     3         return 0;
     4
     5     dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
     6     dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
     7     dev->touch = pkt[0] & 0x01;
     8
     9     return 1;
    10 }


usbtouch_process_multi:用于中断回调函数,用于上传数据

   12 static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
    13                                    unsigned char *pkt, int len)
    14 {

  ...............

   34         tmp = pkt_len - usbtouch->buf_len;
    33         if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size)
    32             goto out_flush_buf;
    31         memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
    30         usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len);

  ................

    25         if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
    24             usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len);
    23         } else {
    22             /* incomplete packet: save in buffer */
    21             memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
    20             usbtouch->buf_len = buf_len - pos;
    19             return;
    18         }

  ................



  1292 static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,                                                                                                                                       
  1                                  unsigned char *pkt, int len)
     2 {
  ............
   8     input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch);
   
    14         input_report_abs(usbtouch->input, ABS_X, usbtouch->x);
    15         input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);
 
    17     if (type->max_press)
    18         input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
  19     input_sync(usbtouch->input);
    20 }



最后,简单说一下urb,urb全称:USB request block,可以看作数据运输的工具,主要流程如下:

1.usb设备驱动程序创建并初始化一个访问特定usb设备端点的urb,并提交给usb core。

2.usb core提交该urb到usb主控制器驱动程序

3.usb主控制器驱动程序根据urb描述的信息来访问usb设备

具体流程:

(1)创建urb

struct urb* usb_alloc_urb(int isoc_packets, int mem_flags);

iso_packets:urb 所包含的等时数据包的个数,若不是等时传输则为0。

mem_flags:内存分配标志(如GFP_KERNEL)

(2)中断urb的初始化

void usb_fill_int_urb(struct urb* urb,

struct usb_device* dev,

unsigned int pipe,

void* transfer_buffer,

int buffer_length,

usb_complete_t complete,

void* context,

int interval

);

struct urb* urb:要初始化的urb指针

struct usb_device* dev:要访问的设备

transfer_buffer:收/发数据的缓冲区

buffer_length:缓冲区长度

complete:当完成urb所请求的操作后调用此函数。

context:complete函数所需的上下文,通常值为dev

interval:urb被调度的时间间隔。

pipe:要访问的端点所对应的管道,使用usb_sndintpipe()或usb_rcvintpipe()创建,如下:

pipe是一个管道号,该管道记录了目标设备的端点以及管道的类型。每个管道只有一种类型和一个方向,与他的目标设备的端点相对应,可以通过一下几个函数来获得管道号并设置管道类型:

 unsigned int usb_sndctrlpipe(struct usb_device* dev, unsigned int endpoint):把指定usb设备的指定端点设置为一个控制out端点。

 unsigned int usb_rcvctrlpipe(struct usb_device* dev, unsigned int endpoint):把指定usb设备的指定端点设置为一个控制in端点。

 unsigned int usb_sndbulkpipe(struct usb_device* dev, unsigned int endpoint):把指定usb设备的指定端点设置为一个批量out端点。

 unsigned int usb_rcvbulkpipe(struct usb_device* dev, unsigned int endpoint):把指定usb设备的指定端点设置为一个批量in端点。

 unsigned int usb_sndintpipe(struct usb_device* dev, unsigned int endpoint):把指定usb设备的指定端点设置为一个中断out端点。

 unsigned int usb_rcvintpipe(struct usb_device* dev, unsigned int endpoint):把指定usb设备的指定端点设置为一个中断in端点。

 unsigned int usb_sndisocpipe(struct usb_device* dev, unsigned int endpoint):把指定usb设备的指定端点设置为一个等时out端点。

 unsigned int usb_rcvisocpipe(struct usb_device* dev, unsigned int endpoint):把指定usb设备的指定端点设置为一个等时in端点。


对于批量urb和控制urb,用下面函数:

void usb_fill_bulk_urb(struct urb* urb, struct usb_device* dev, unsigned int pipe, void* transfer_buffer, int buffer_length, usb_complete_t complete, void* context);

void usb_fill_bulk_urb(struct urb* urb, struct usb_device* dev, unsigned int pipe, unsigned char* setup_packet, void* transfer_buffer, int buffer_length, usb_complete_t complete, void* context);


(3)创建和初始化完成后,urb便可以通过usb_submit_urb函数提交到usb核心:

int usb_submit_urb(struct urb* urb, gfp_t mem_flags)

urb:指向urb的指针

mem_flags:内存分配标志,用于告诉usb核心如何分配内存缓冲区。

mem_flags的几种标志:GFP_ATOMIC、GFP_NOIO、GFP_KERNEL,一般在中断上下文环境中我们会用GFP_ATOMIC

(4)提交后,urb会调用回调函数,回调函数主要检查status字段(当一个urb把数据送到设备时,这个urb会由系统返回给驱动程序,并调用驱动程序的urb完成回调函数处理,这是status记录了这次数据传输的有关状态,如是否成功,成功则返回0),以确定数据是否传输成功.


usb中的endpoint和传输模式可以参考一下:http://blog.chinaunix.net/uid-25314474-id-3040231.html






















  

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

USB触摸屏的驱动 的相关文章

  • idea2022更改本地仓库,配置阿里云中央仓库

    注意 files setting与files other settings是不同的东西 因为idea版本的不同 其他设置的称呼都不同 idea2022的other settings指的是截图所示 解决 要想每次新建项目的仓库路径为自己设置的
  • Linux--PAM机制

    Linux PAM机制 文章目录 Linux PAM机制 一 PAM是什么 二 PAM模块设置语法 2 1 etc pam d 里面的配置文件 2 1 1第一个字段 验证类别 Type 2 1 2第二个字段 验证的控制标识 control
  • Product 1 Modulo N

    Product 1 Modulo N 题意 给一个n 2 lt n lt 1e5 找到排列 1 2 n 1 的最长子序列 使得它元素的乘积模n意义下为1 输出子序列长度以及子序列 思路 考虑1 n 1中那些元素可以选 如果x与n不互质 即g
  • IAF R-CNN:针对多光谱行人目标检测的光照感知Faster R-CNN

    目录 论文下载地址 论文作者 模型讲解 背景介绍 论文解读 FasterR CNN用于多光谱行人目标检测 融合结构 其他设置 多光谱行人目标检测基准 结果 光照感知的FasterR CNN 光照估算模块 门控融合模块 优化过程 结果分析 实
  • 12分钟入门python基础-计算机视觉方向

    0 环境搭建和界面使用 0 1命名规范 函数和变量为了方便代码阅读最好使用标准的英文 有的高校在大学生进行代码学习的时候就有着用英语进行命名的要求 对于常量一般设置为大写 比如ALL 对于变量一般遵循小写字母并且通过下划线的方式进行连接 对
  • img在div中水平且垂直居中

    一 问题背景 情况 div包着一个img 要使img水平且垂直居中 二 解决方案 最最最关键 div中的text align center 是必须填的 如下 div style text align center class img img
  • 基于leptonica-1.78.0的.cppan文件夹

    在编译tesseract 的过程中 有一步是调用cppan命令下载依赖库 而这一步往往会依赖库下载不全 为了方便大家 文件夹的网盘链接如下 大家下好后复制到C Users Administrator文件夹下即可 链接 https pan b
  • 看完这篇 教你玩转渗透测试靶机vulnhub——HackNos-2.1

    Vulnhub靶机HackNos 2 1渗透测试详解 Vulnhub靶机介绍 Vulnhub靶机下载 Vulnhub靶机安装 Vulnhub靶机漏洞详解 信息收集 漏洞利用 SSH登录 sudo su 提权 获取flag Vulnhub靶机
  • edu99 div.2 Sequence and Swaps优雅的暴力

    time limit per test1 5 seconds memory limit per test512 megabytes inputstandard input outputstandard output Example inpu
  • 多输出数据的回归:随机森林回归和多输出元估计器回归效果对比

    多输出数据的回归 随机森林回归和多输出元估计器回归效果对比 在机器学习中 我们常常需要预测多个输出变量 例如 在房产市场上 我们可能需要预测一个房子的价格 面积 位置等多个属性 这就是所谓的多输出数据的回归问题 本文将介绍两种流行的多输出回
  • Mysql的基本操作-增删改查

    目录 一 分类 1 DDL 2 DML 3 DCL 二 数据库的四个命令 1 数据库操作 2 常用数据类型 2 1 数值类型 2 2 字符串类型 2 3 期类型 三 表的使用 1 表的操作 3 1创建表 3 2删除表 3 3查看表结构 3
  • 设计师都去哪些网站找样机素材

    在当今的设计领域 3D样机素材已经成为一个重要的领域 3D样机素材可以让设计师更好地展示他们的设计理念和概念 也可以帮助客户更好地理解设计 为了帮助设计师更容易地创建3D样机素材 以下是我推荐的10个易于使用的3D样机素材网站 即时设计资源
  • 一篇文章教你顺利入门和开发chrome扩展程序(插件)

    前言 关于chrome extension的开发经验总结或说明文档等资料很多 很多人在写 然而 我也是一员 但是 也许这篇文章 可能给你一些不一样的感受 这里介绍的是80 你要开发扩展会碰到的问题 前面部分大多数是一些基础介绍 和别人的资料
  • 如何快速学习Java语言

    除了一般性的建议 比如制定学习计划 学教程 看书 使用IDE等等 还有一些特殊的方法可以帮助您更快速高效地学习Java语言 以下是一些特殊的学习方法 项目驱动学习 选择一个小型的实际项目 并利用Java来实现它 这样的项目可以是一个简单的命
  • Java Web应用开发 考试题库 答案

    一 选择题 共10小题 每小题2分 共20分 1 以下哪种情况是出现500报错的原因 A jsp页面出现语法错误导致无法编译 B 表单中的action地址与处理该表单的servlet映射地址不一致 C 用户访问的url地址不对或不存在 D
  • MongoDB去重

    对MongoDB的数据中某一列进行去重 可直接使用aggregate聚合函数和distinct去重函数 table aggregate match group id id1 sort count 1 table distinct id1 Q
  • 数字化发展的三个阶段

    数字化发展主要经历的概念变迁包括 数字转换 digitization 数字化 digitalization 数字化转型 digital transformation 1 数字转换 数字转换 digitization 最早出现在1954年 是
  • centos7换源

    1 首先备份系统自带yum源配置文件 etc yum repos d CentOS Base repo mv etc yum repos d CentOS Base repo etc yum repos d CentOS Base repo
  • MyEclipse无法打开server视图的解决办法

    解决办法 1 首先打开MyEclipse工作空间 2 然后删除工作空间下的 metadata plugins org eclipse core runtime settings com genuitec eclipse ast deploy
  • python中的for循环搭配else

    经常会看到for循环和else一起搭配的情形 这不是你的代码缩进不对 而是本身就有这种语法结构 for i in range 100 else for i in range n if s index s i t index t i retu

随机推荐

  • Docker 配置 MySQL

    文章目录 前言 正文 检查是否存在 MySQL 镜像 删除已经安装的 MySQL 镜像 拉取指定版本的镜像 运行MySQL镜像并设置密码 查看MySQL镜像是否运行 进入运行的容器 进入 MySQL 服务 查看数据文件位置 外部连接MySQ
  • 【计算机网络】IP地址详解

    计算机网络 IP地址详解 Shadow丶S的博客 CSDN博客 计算机网络ip
  • Linux下c和cuda混合编译,并生成动态链接库.so和使用

    Linux下c和cuda混合编译 并生成动态链接库 so和使用 2016 08 27 14 27 98人阅读 评论 0 收藏 举报 分类 Linux 版权声明 本文为博主原创文章 未经博主允许不得转载 目录 梗概 如果要生成动态链接库 就需
  • 经典嵌入式开发学习网站推荐

    原文地址 http blog csdn net david luyang article details 6621065 1 EG3 关于嵌入式开发的站点 提供非常多关于嵌入式开发的资料 包括开发公司 技术文档 免费资源等等 版面包括bus
  • Vue项目实战 —— 哔哩哔哩移动端开发—— 第一篇

    目录 前言完 效果图 登录含签权 注册带正则 个人中心 下拉加载更多主页 修改个人中心 视频播放加关注 收藏 评论盖楼A回复B B回复C C回复A类似 项目开始 封装登录 注册 封装登录 从零到一开发一个 哔哩哔哩移动端App 包括后面的打
  • (python实现)最长公共子序列-2022-12-16

    算法思想 算法解释参考 算法图解 ISBN 978 7 115 44763 0 详细求解参考 算法 最长公共子序列 输出所有最长公共子序列 Python实现 主要利用了动态规划思想 从小问题着手 算法举例解释 代码实现 由上图的思路总结 可
  • git上传项目和拉取项目

    一 git上传项目和拉取项目 github创建仓库完成后 默认有两个仓库分别是main和master 默认拉取和上传操作针对于main仓库 是可以更改默认仓库的 至于如何更改默认仓库详情百度 1 在github上创建仓库 之前没有创建仓库的
  • 【猿人学WEB题目专解】猿人学第6题

    据说 看我文章时 关注 点赞 收藏 的 帅哥美女们 心情都会不自觉的好起来 前言 作者简介 大家好我是 user from future 意思是 来自未来的用户 寓意着未来的自己一定很棒 个人主页 点我直达 在这里肯定能找到你想要的 专栏介
  • 安卓Termux搭建web服务器【公网远程手机Android服务器】

    文章目录 概述 1 搭建apache 2 安装cpolar内网穿透 3 公网访问配置 4 固定公网地址 5 添加站点 概述 Termux是一个Android终端仿真应用程序 用于在 Android 手机上搭建一个完整的Linux 环境 能够
  • 前端发送Fetch请求实现流式请求、模拟打字机效果等

    前端需要接收后端的流式返回数据 并实时渲染 普通的xhr请求都是等http协议数据包一次性返回之后才渲染 类似于ChatGPT的Http接口内容类型为text event stream 这种内容类型需要与浏览器建立持久连接并持续监听服务器返
  • java和c++中父类指针(或引用)指向子类对象的一点理解

    c 如果Animal类中存在一个speak 函数 当子类Dog重写了speak 函数后 使用一个父类指针 Animal animal new Dog 指向子类时 子类调用speak 实际上调用的是父类中的speak 函数 地址早绑定 必须将
  • Linux使用HTTP隧道代理代码示例模版

    以下是一个使用HTTP隧道代理的示例代码模板 python import requests def send request url proxy host proxy port 设置代理 proxies http f http proxy
  • Docker 可以共享主机的参数

    命令 docker run it ipc host ubuntu latest bin bash docker run it net host ubuntu latest bin bash docker run it pid host ub
  • Python基础编程练习(1)编写程序,生一个成包含1000个0~100之间的随机整数的列表

    Python基础编程练习 1 编写程序 生一个成包含1000个0 100之间的随机整数的列表 编写程序 生一个成包含1000个0 100之间的随机整数的列表 要求 1 统计每个整数出现的次数 2 将前500个元素升序排列 后500个降序排列
  • ssm(spring+springMVC+Mybatis)框架集成Mongodb

    1 开发环境 JDK 1 6 ssm框架关联jar包 aopalliance jar aspectjrt jar aspectjweaver jar commons beanutils 1 9 2 jar commons codec 1 9
  • 推荐系统公平性论文阅读(六)

    做为最后一篇论文阅读记录 我决定对我目前为止粗读和精读的论文进行一次总结 然后陈述一些个人对该研究领域的见解和想法 论文总结归纳 推荐系统中的偏差和不公平现象是随着推荐算法的诞生就与生俱来的 而不是人为故意产生的 目前我读过的论文中包括的一
  • 弹出页面之间传值

    弹出页面之间传值 假如A页面需要弹出B页面 在比页面关闭时 A页面要拿到B页面的需要值 思路可以认为是 1 在A页面中利用Window Open 方法
  • 页面埋点方案

    前段时间调查了下页面埋点方案 参考http blog csdn net hxyascx article details 53373916 1 在页面加入一段js 该js可以远程加载获取信息的js脚本 2 该脚本创建Image对象 3 暂时脚
  • 48种世间哲学,其中值得借鉴的有10个

    无图片版 1 绝对主义 absolutism 色盲 绝对主义认为在任何一种学说里 某种观点必定是绝对正确或者绝对错误的 点评 没什么可说的 连影视剧都已经放弃了绝对主义 2 荒诞主义 absurdism 恶搞 荒诞主义 是对人生的极端反叛
  • USB触摸屏的驱动

    我们都知道410c没有配套的触摸屏 如果有屏的话 在调试或者其他方面就方便多了 所以我们自己买了一个usb触摸屏 现在让我们看看usb触摸屏的驱动 驱动路经 drivers input touchscreen usbtouchscreen