usb之鼠标作为按键输入
1. 首先搞清楚,鼠标点左键、右键等能得到什么数据,然后分析这些数据上报事件即可。
第一个基本点:usb_alloc_urb函数,创建一个struct urb结构体,只能使用这个函数来创建,它是urb在usb世界里的独家代理。
第二个基本点:usb_fill_control_urb函数,初始化一个控制urb,urb被创建之后,使用之前必须要正确的初始化。里面包含有usb的中断服务函数。
第三个基本点:usb_start_wait_urb函数,将urb提交给咱们的usb core,以便分配给特定的主机控制器驱动进行处理,然后默默的等待处理结果,或者超时。
2. 最主要的是urb的使用
2.1 获得当前可用的或者说活跃的接口:
- interface = intf->cur_altsetting; //接口
2.2 从接口获得端点
- endpoint = &interface->endpoint[].desc; //端点
2.3 搞清楚源、目的、长度
- len = endpoint->wMaxPacketSize; //长度(多少字节)
- buf = usb_alloc_coherent(mdev, len, GFP_ATOMIC, &mouse_dma); //传输buffer,目的
- pipe=usb_rcvintpipe(mdev,endpoint->bEndpointAddress); //源
2.4 接下来就是创建urb(usb request block)
- mouse_urb = usb_alloc_urb(, GFP_KERNEL);
2.5 初始化urb
- usb_fill_int_urb(mouse_urb,mdev,pipe,buf,len,usb_mouse_irq, NULL, endpoint->bInterval); //初始化中断型urb结构体
2.6 定义urb的dma传输地址和传输类型
- mouse_urb->transfer_dma = mouse_dma;
- mouse_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
2.7 发送异步传输请求
- usb_submit_urb(mouse_urb, GFP_KERNEL);
发送异步传输请求后,就等待目的buffer接收到数据,然后进入中断usb_mouse_irq。
3 关于函数usb_kill_urb(mouse_urb)
kref——urb的引用计数。主机与设备之间通过管道传输数据,管道的一端是主机上的一个缓冲区,另一端是设备上的端点。管道之中流动的数据,在主机控制器和设备看来是一个个packets,在咱们看来就是urb。因而,端点之中就有那么一个队列,叫urb队列。不过,这并不代表一个urb只能发配给一个端点,它可能通过不同的管道发配给不同的端点,那么这样一来,我们如何知道这个urb正在被多少个端点使用,如何判断这个urb的生命已经over?如果没有任何一个端点在使用它,而我们又无法判断这种情况,因此需要引用计数。每多一个使用者,它的这个引用计数就加1,每减少一个使用者,引用计数就减一,如果连最后一个使用者都释放了这个urb,宣称不再使用它了,那它的生命周期就走到了尽头,会自动的销毁。
其实它是一个struct kref结构体,在include/linux/kref.h里定义,别看这个结构体简单,内核里就是使用它来判断一个对象是否有用。它里边儿只包括了一个原子变量,为什么是原子变量?既然都使用引用计数了,那就说明可能同时有多个地方在使用这个对象,总要考虑一下它们同时修改这个计数的可能性吧,也就是俗称的并发访问,那怎么办?加个锁?就这么一个整数值专门加个锁未免也忒大材小用了些,所以就使用了原子变量。围绕这个结构,就多说一点吧。内核里还定义了几个专门操作引用计数的函数,它们在lib/kref.c里定义,包括kref_init,kref_get,kref_put等函数。kref_init初始化,kref_get将引用计数加1,kref_put将引用计数减一并判断是不是为0,为0的话就调用参数里release函数指针指向的函数把对象销毁掉。友情提醒一下,kref_init初始化时,是把refcount的值初始化为1了的,不是0。还有一点要说的是kref_put参数里的那个函数指针,你不能传递一个NULL过去,否则这个引用计数就只是计数,而背离了最初的目的,要记住我们需要在这个计数减为0的时候将嵌入这个引用计数struct kref结构体的对象给销毁掉,所以这个函数指针也不能为kfree,因为这样的话就只是把这个struct kref结构体给销毁了,而不是整个对象。
如何使用struct kref结构来为我们的对象计数?当然我们需要把这样一个结构嵌入到你希望计数的对象里边,不然你根本就无法对对象在它整个生命周期里的使用情况作出判断。但是我们应该是几乎见不到内核里边儿直接使用上面那几个函数来给对象计数的,而是每种对象又定义了自己专用的引用计数函数,比如咱们的urb,在drivers/usb/core/urb.c里定义。usb_init_urb、usb_get_urb、usb_free_urb这三个函数分别调用了前面看到的struct kref结构的三个操作函数来进行引用计数的初始化、加1、减一。什么叫封装?这就叫封装。usb_init_urb和usb_get_urb都没什么好说的,比较感兴趣的是usb_free_urb里给kref_put传递的那个函数urb_destroy,它也在urb.c里定义。这个urb_destroy首先调用了to_urb,实际上就是一个container_of来获得引用计数关联的那个urb,然后使用kfree将它销毁。
use_count,这里又是一个使用计数,不过此计数非彼计数,它与上面那个用来追踪urb生命周期的kref一点儿血缘关系也没。那它是用来做什么的?简单说一下使用urb来完成一次完整的usb通信都要经历哪些阶段:首先,驱动程序发现自己需要与usb设备通信,于是创建一个urb结构体,并指定它的目的地是设备上的哪个端点,然后提交给usb core,usb core将它做一些初始化后再移交给主机控制器的驱动程序HCD,HCD会去解析这个urb,了解它的目的是什么,并与usb设备进行相应的交流,在交流结束,urb的目的达到之后,HCD再把这个urb的所有权移交回驱动程序。这里的use_count就是在usb core将urb移交给HCD的时候使用。什么时候减1?在HCD重新将urb的所有权移交回驱动程序的时候。这样说吧,只要HCD拥有这个urb的所有权,那么该urb的use_count就不会为0。这么一说,似乎use_count也有点追踪urb生命周期的味道了,当它的值大于0时,就表示当前有HCD正在处理它,和上面的kref概念上有部分的重叠,不过,显然它们之间是有区别的。上面的那个kref实现方式是内核里统一的引用计数机制,当计数减为0时,urb对象就被urb_destroy给销毁了。这里的use_count只是用来统计当前这个urb是不是正在被哪个HCD处理,即使它的值为0,也只是说明没有HCD在使用它而已,并不代表就得把它给销毁掉。比方说,HCD利用完了urb,把它还给了驱动,这时驱动还可以对这个urb检修检修,再提交给哪个HCD去使用。
创建urb结构体并提交后,到达了HCD那里正在处理中,突然驱动反悔了,它不想继续这次通信了,想将这个urb给终止掉,这时usb core当然会给驱动提供这样的接口来满足这样的需要。那么怎么办呢?写内核的兄弟还是考虑到这里了,想到了两种处理方法。一种是驱动只想通过usb core告诉HCD一声,说这个urb我想终止掉,您就别费心再处理了,然后它不想在那里等着HCD的处理,想忙别的事去,这就是俗称的异步,对应的是usb_unlink_urb函数。另一种就是同步处理,驱动会在那里苦苦等候着HCD的处理结果,等待着urb被终止,对应的是usb_kill_urb函数。而HCD将这次通信终止后,同样会将urb的所有权移交回驱动。那么驱动通过什么判断HCD已经终止了这次通信?就是通过这里的use_count,驱动会在usb_kill_urb里面一直等待着这个值变为0。拿到urb的控制权之后,就可以调用usb_free_urb释放urb了。
详细的代码见:https://www.cnblogs.com/zhu-g5may/p/9311006.html
4、最后通过make menuconfig 去掉原来内核自带的鼠标驱动,它们的usb_driver的id_table中都支持鼠标设备,使得它们的probe函数都会执行,产生冲突。其实自带usbmouse.o并没有编译进内核,而是有鼠标插入动态加载usbmouse.ko驱动,所以可以rmmod usbmouse.ko,然后insmod我们自己的驱动程序。
usb之鼠标作为按键输入的更多相关文章
- linux下如何模拟按键输入和模拟鼠标【转】
转自:http://www.cnblogs.com/leaven/archive/2010/11/30/1891947.html 查看/dev/input/eventX是什么类型的事件, cat /p ...
- linux输入子系统(input subsystem)之按键输入和LED控制
实验现象:在控制台打印按键值,并且通过按键控制相应的LED亮灭. 1.代码 input_subsys_drv.c #include <linux/module.h> #include &l ...
- Python脚本控制的WebDriver 常用操作 <十二> send_keys模拟按键输入
下面将使用WebDriver中的send_keys来模拟键盘按键输入 测试用例场景 send_keys方法可以模拟一些组合键操作: ctrl+a ctrl+c ctrl+v 等. 另外有时候我们需要在 ...
- ADB——模拟手机按键输入
基本命令 adb 模拟按键输入的命令主要通过 input 进行 Usage: input [<source>] <command> [<arg>...] The s ...
- adb命令模拟按键输入keycode
adb命令模拟按键输入keycode 2017年05月18日 14:57:32 阅读数:1883 例子: //这条命令相当于按了设备的Backkey键 adb shell input keyevent ...
- STM32基本GPIO操作:按键输入(扫描+外部中断)
(涉及专有名词较多,难免解释不到位,若有错误还请指出,谢谢!) 硬件连接图如下: 一.扫描 思路是在main函数中通过死循环来扫描端口电平状态检测,以此判断按键是否按下.实现较为简单. 1.初始化(注 ...
- adb shell命令模拟按键/输入input使用keycode 列表详解
在adb shell里有一个非常使用的命令,模拟按键输入,这里首先不要理解为是键盘的模拟按键,下面命令的使用和键值做一个详解. input命令格式 adb shell input keyevent & ...
- Helium文档5-WebUI自动化-press模拟键盘按键输入技巧
前言 press方法是用来模拟键盘按键输入,可以组合使用,来模拟键盘输入,解决一些难定位的元素 入参介绍 以下是press源码中的函数介绍 def press(key): :入参 :param ke ...
- USB限流IC,输入5V,输出5V,最大3A限流
USB限流芯片,5V输入,输出5V电压,限流值可以通过外围电阻进行调节,PWCHIP产品中可在限流范围0.4A-4.8A,并具有过压关闭保护功能. 过压关闭保护: 如芯片:PW1555,USB我们一半 ...
随机推荐
- update_dctcp_alpha
/* + * Update dctcp alpha based on the ecn bit in the received packet. + * This procedure is called ...
- SQL Server 没有足够的内存继续执行程序 (mscorlib)的解决办法
问题: SQL Server 执行大脚本时,出现如下提示信息: 解决方法: 使用 sqlcmd.exe 导入 1.win + r,输入 cmd 进入 C:\Program Files\Microsof ...
- Linux Mint 18.2安装后需要进行的设置
自己的笔记本电脑升级到win10后各种不好用,运行速度慢,开关机时间很长,系统也是经常性的更新,外加发热严重.更改设置和更换驱动都没能解决问题.另外感觉在Linux下能够更加专注,所以索性将主系统更换 ...
- Oracle 12C pluggable database自启动
实验环境创建了两个PDB,本实验实现在开启数据库时,实现pluggable database PDB2自启动: 原始环境: SQL> shu immediateDatabase closed.D ...
- 【深入理解JAVA虚拟机】第5部分.高效并发.1.Java内存模型与线程。
1.概述 摩尔定律:描述处理器晶体管数量与运行效率之间的发展关系.Amdahl定律:通过系统中并行化与串行化的比重来描述多处理器系统能获得的运算加速能力. 从摩尔定律到Amdahl定律的转变,代表了近 ...
- Windows下设置Ubuntu引导项
最近在进行一些实验环境的配置,最终通过双系统实现了多系统的管理,而不仅限于虚拟机的方式.以此方式成功安装了Windows8.1 Pro和Windows 10,原文在此. 在此基础上进一步安装了 Ubu ...
- IntelliJ IDEA 2017 完美注册方法及破解方法
本文使用破解方式注册. 下载破解文件JetbrainsCrack-2.6.2.jar 下载地址: http://idea.lanyus.com/ 开始破解 一.将下载的 JetbrainsCrack- ...
- 手把手教你自定义attr
最近在学习的过程中遇到了自定义的attr和自定义的style.因此各种百度,各种博客的学习,算是有了一个系统的了解.在这里记录下自己的收获. 一.为什么要使用自定义attr以及本文定位 在androi ...
- 解析纯真IP地址库
一周以来,一直在做 IP地址库的解析.从调研到编码到优化,大概花了有七八天的时间.感觉很好玩.总结一下整个做的过程. 1.关于IP 地址库的解析方式 目前主要的解析方式有两种:通过API,或通过IP数 ...
- PHP-----TP框架基础
TP框架基础 把Thinkphp框架的压缩包解压到php文件夹下----www目录下. Thinkphp文件夹都有什么呢??? (所有用TP框架做的程序,要访问程序里面的网页.内容的话,全部要走这 ...