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我们一半 ...
随机推荐
- 关于派生类访问基类对象的保护变量的问题 --Coursera
https://class.coursera.org/pkupop-001/forum/thread?thread_id=350 郭天魁· 6 months ago 在课件中我们知道如下程序是不能 ...
- tomcat运行报错Failed to start component [StandardEngine[Catalina].StandardHost[localhost].
tomcat运行报错Failed to start component [StandardEngine[Catalina].StandardHost[localhost].多半情况是找不到jar包 解 ...
- onchange,onfocus ,oninput事件
compositionstart 在输入一段需要确认的文本如拼音to汉字.语音时会触发 compositionend 在拼音选词完成.语音输入完毕时会触发 addEventListener() 方法 ...
- typeof操作符和instanceof操作符的区别 标签: JavaScript 2016-08-01 14:21 113人阅读 评论(
typeof主要用于检测变量是不是基本数据类型 typeof操作符是确定一个变量是字符串.数值.布尔类型,还是undefined的最佳工具.此外,使用typeof操作符检测函数时,会返回"f ...
- 基于SAP Kyma的订单编排增强介绍
尽管有一万个舍不得,2018年还是无可挽回地离我们远去了. 唯有SAP成都研究院的同事和我去年在网络上留下的这些痕迹,能证明2018年我们曾经很认真地去度过每一天: SAP成都研究院2018年总共87 ...
- Dom4j的一个小例子,用于解析xml文件的元素获取方式
import java.io.File; import java.io.IOException; import javax.xml.parsers.ParserConfigurationExcepti ...
- java里面list是引用的好例子
java里面的赋值和引用是不同的,以后要详细总结一下! 看一个例子: public static void main(String[] args) { List<String> list ...
- Spring AOP 的切点切在Controller上没有起作用的问题。
做下笔记,以防忘记. 在Spring MVC 中使用面向切面编程,感觉所有的配置.切面.切点的编写都没有写错,但是当切点切在@Controller注解的类的方法上时就不起作用.当切点切在的其他的非@C ...
- webstorm&phpstorm打开大型项目卡死解决如vue-laravel-Yii2
用phpstorm开发时如果项目中文件过多会造成phpstorm变慢甚至卡死,尤其在node加入到我们的项目中更加会加重这种情况,因为node_modules目录中的模块非常多,phpstorm加载这 ...
- 给已安装的NGINX添加新的模块
给已安装的NGINX添加新的模块 2018-11-16 14:02:45 Visit 0 使用 nginx -V 查看当前nginx的信息,包括版本号和configure编译配置信息 版本号 : ...