有监听时鼠标的每一次动作(左键一次按下或左键一次弹起),都会对应三个中断(vic_handle_irq -> ... -> ohci_irq)ohci instatus 为 6 或者 26每一次按下左键,对应3个event(每个中断上报一个event),都会调用 mousedev_event 上报第三次(表示一次动作结束)的时候read会被唤醒,得到具体数据
无监听时鼠标的每一次动作,都不会发生中断,也不会有后面的数据传输等过程上报路径有很多,对应不同的设备文件input-event         : /dev/input/event0input-mousedev       : /dev/input/mouse0 和 /dev/input/miceusb_mouse_driver    : /dev/???/dev/input/mouse0  /dev/input/mice对应 input-mousedev drivers/input/mousedev.cmousedev_readwait_event_interruptible(mousedev->wait// 一次按下,对应3次调用mousedev_event // 被调用3次mousedev_notify_readerswake_up_interruptible(&mousedev->wait);将数据上报给用户

上报相关的API

  • mousedev_event
[<c03b0bb8>] (mousedev_event) from [<c03aa794>] (input_to_handler+0xf8/0x104)
[<c03aa794>] (input_to_handler) from [<c03ab30c>] (input_pass_values.part.1+0x124/0x13c)
[<c03ab30c>] (input_pass_values.part.1) from [<c03ac3a4>] (input_handle_event+0x134/0x60c)
[<c03ac3a4>] (input_handle_event) from [<c03ac8a4>] (input_event+0x28/0x30)
[<c03ac8a4>] (input_event) from [<c041fce0>] (hidinput_report_event+0x50/0x70)
[<c041fce0>] (hidinput_report_event) from [<c041dc64>] (hid_report_raw_event+0x220/0x460)
[<c041dc64>] (hid_report_raw_event) from [<c041dfac>] (hid_input_report+0x108/0x180)
[<c041dfac>] (hid_input_report) from [<c042a2ac>] (hid_irq_in+0x1b8/0x268)
[<c042a2ac>] (hid_irq_in) from [<c038d384>] (__usb_hcd_giveback_urb+0x54/0xdc)
[<c038d384>] (__usb_hcd_giveback_urb) from [<c03a1f88>] (finish_urb+0x68/0xf4)
[<c03a1f88>] (finish_urb) from [<c03a3428>] (ohci_work.part.2+0x28c/0x4e0)
[<c03a3428>] (ohci_work.part.2) from [<c03a76c0>] (ohci_irq+0x190/0x2c8)
[<c03a76c0>] (ohci_irq) from [<c038cc88>] (usb_hcd_irq+0x24/0x38)
[<c038cc88>] (usb_hcd_irq) from [<c01479f8>] (__handle_irq_event_percpu+0x40/0x128)
[<c01479f8>] (__handle_irq_event_percpu) from [<c0147b08>] (handle_irq_event_percpu+0x28/0x7c)
[<c0147b08>] (handle_irq_event_percpu) from [<c0147b84>] (handle_irq_event+0x28/0x3c)
[<c0147b84>] (handle_irq_event) from [<c014b63c>] (handle_level_irq+0x9c/0x114)
[<c014b63c>] (handle_level_irq) from [<c01472b4>] (generic_handle_irq+0x30/0x44)
[<c01472b4>] (generic_handle_irq) from [<c0147310>] (__handle_domain_irq+0x48/0xa8)
[<c0147310>] (__handle_domain_irq) from [<c030e98c>] (vic_handle_irq+0x58/0x9c)
[<c030e98c>] (vic_handle_irq) from [<c0100b4c>] (__irq_svc+0x6c/0x90)
上面只看到了调用堆栈,但是没提到 device 发送的数据 是何时获取的
按道理,中断之前 已经将 传输描述符TD  放到 done 列表了
中断处理程序只需要从 done 列表中的 传输描述符TD 拿取数据就行了
ohci_irqif (ints & OHCI_INTR_WDH) update_done_listtd_dma = hc32_to_cpup (ohci, &ohci->hcca->done_head);td = dma_to_td (ohci, td_dma);add_to_done_list(ohci, td);ed = td->ed;list_for_each_entry_continue_reverse(td2, &ed->td_list, td_list)ohci_workprocess_done_listtakeback_tdfinish_urbusb_hcd_giveback_urb__usb_hcd_giveback_urburb->complete(urb);finish_unlinks
usb/host/ohci-q.c 中的调用关系
ohci_workprocess_done_listtakeback_tdstart_ed_unlinked_deschedulefinish_urbfinish_unlinksfinish_urbed_schedulefinish_unlinks

监听相关的API

$ sudo strace hexdump  /dev/input/mouse0
read(0, "\t\0\0", 4096)                 = 3
read(0, "\10\0\0", 4096)                = 3
read(0, "\t\0\0", 4096)                 = 3
read(0, "\10\0\0", 4096)                = 3
read(0, "\t\0\0", 4096)                 = 3
read(0, "\10\0\0", 4096)                = 3
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x9), ...}, AT_EMPTY_PATH) = 0
write(1, "0000000 0009 0800 0000 0009 0800"..., 480000000 0009 0800 0000 0009 0800 0000 0009 0800
) = 48
read(0, "\t\0\0", 4096)                 = 3
read(0, "\10\0\0", 4096)                = 3
read(0, "\t\0\0", 4096)                 = 3
read(0, "\10\0\0", 4096)                = 3
read(0, "\t\0\0", 4096)                 = 3
write(1, "0000010 0000 0009 0800 0000 0009"..., 480000010 0000 0009 0800 0000 0009 0800 0000 0009
) = 48
read(0, "\10\0\0", 4096)                = 3
read(0, "\t\0\0", 4096)                 = 3
read(0, "\10\0\0", 4096)                = 3
read(0, "\t\0\0", 4096)                 = 3
read(0, "\10\0\0", 4096)                = 3
write(1, "0000020 0800 0000 0009 0800 0000"..., 480000020 0800 0000 0009 0800 0000 0009 0800 0000$ sudo hexdump  /dev/input/mouse0
0000000 0009 0800 0000 0009 0800 0000 0009 0800
0000010 0000 0009 0800 0000 0009 0800 0000 0009
0000020 0800 0000 0009 0800 0000 0009 0800 0000[<c03b12f8>] (mousedev_read) from [<c01c70f0>] (vfs_read+0xa4/0x2d4)
[<c01c70f0>] (vfs_read) from [<c01c7ae8>] (ksys_read+0x4c/0xd4)
[<c01c7ae8>] (ksys_read) from [<c0100080>] (ret_fast_syscall+0x0/0x58)

USB 中断传输体现在哪里

应该在 ohci_work  中
ohci_irq -> ohci_work -> finish_urb -> __usb_hcd_giveback_urb  -> hid_irq_in
ohci_irq -> ohci_work -> finish_urb -> __usb_hcd_giveback_urb  -> usb_mouse_irq注意 : usb_mouse_irq 和 hid_irq_in 是同级的,这个函数所在的模块都创建了 input device ,并 对应的 complete 成员 在 usb mouse 来数据时 被 调用usb_mouse_irq /hid_irq_in  的类型相同, 都为 void (*p)(struct urb *urb);都做了两个动作1. 将 urb 的 数据取了出来,上报.2. 调用 usb_submit_urb(urb, GFP_ATOMIC); // 这个是重新提交 urb到 usb core所以说 下次中断来的时候, 1.会用鼠标发送来的数据填充这个 urb的数据成员(TODO,何时呢?大概是ohci_irq 后,__usb_hcd_giveback_urb  调用 complete前)2.然后调用 usb_mouse_irq 和 hid_irq_in  ,让其"1.拿数据上报 2.重新提交urb"
所以说 对于 一个 usb 鼠标设备,只存在一个urb第一次提交是在什么时候呢?在 打开鼠标设备文件时
usb_submit_urb
[<c0429c84>] (hid_start_in) from [<c0429ea4>] (usbhid_open+0xb0/0x174)
[<c0429ea4>] (usbhid_open) from [<c041e74c>] (hid_hw_open+0x44/0x64)
[<c041e74c>] (hid_hw_open) from [<c03aca74>] (input_open_device+0x80/0xc0)
[<c03aca74>] (input_open_device) from [<c03b0754>] (mousedev_open_device+0x58/0x6c)
[<c03b0754>] (mousedev_open_device) from [<c03b087c>] (mousedev_open+0x78/0xd4)
[<c03b087c>] (mousedev_open) from [<c01cbb2c>] (chrdev_open+0x60/0x13c)
[<c01cbb2c>] (chrdev_open) from [<c01c37dc>] (do_dentry_open+0x11c/0x394)
[<c01c37dc>] (do_dentry_open) from [<c01d5790>] (path_openat+0xb20/0xcd8)
[<c01d5790>] (path_openat) from [<c01d59b4>] (do_filp_open+0x6c/0xdc)
[<c01d59b4>] (do_filp_open) from [<c01c3c64>] (do_sys_openat2+0x210/0x2ec)
[<c01c3c64>] (do_sys_openat2) from [<c01c55b4>] (do_sys_open+0xa4/0xd4)
[<c01c55b4>] (do_sys_open) from [<c0100080>] (ret_fast_syscall+0x0/0x58)在什么时候 将这个urb 结束呢关闭文件时,usbhid_close -> usb_kill_urb(usbhid->urbin);
usb_kill_urb
[<c0429c64>] (usbhid_close) from [<c041e7a8>] (hid_hw_close+0x3c/0x48)
[<c041e7a8>] (hid_hw_close) from [<c03acb88>] (input_close_device+0x88/0x8c)
[<c03acb88>] (input_close_device) from [<c03b02d8>] (mousedev_close_device+0x48/0x54)
[<c03b02d8>] (mousedev_close_device) from [<c03b03d8>] (mousedev_release+0x38/0x44)
[<c03b03d8>] (mousedev_release) from [<c01c8ec8>] (__fput+0x74/0x218)
[<c01c8ec8>] (__fput) from [<c012b4b4>] (task_work_run+0x6c/0xa0)
[<c012b4b4>] (task_work_run) from [<c01146a0>] (do_exit+0x398/0x9f8)
[<c01146a0>] (do_exit) from [<c0114d68>] (do_group_exit+0x3c/0xa4)
[<c0114d68>] (do_group_exit) from [<c011f268>] (get_signal+0x164/0x7d0)
[<c011f268>] (get_signal) from [<c0103ec0>] (do_work_pending+0x140/0x598)
[<c0103ec0>] (do_work_pending) from [<c01000f0>] (slow_work_pending+0xc/0x20)所以,只有open设备后(close设备前),才会存在该设备的urb(否则该urb不存在) , 才会有该设备的中断传输 .host 每隔1ms发起一次,如果设备没有数据(不会在线上传送有有效数据,但是有ack,这就是中断传输),则不会中断host 每隔1ms发起一次,如果设备有数据(会在线上传送有有效数据,这就是中断传输),则会中断这个urb 是在什么时候alloc的呢?usb_mouse_probe时/usbhid_start时

鼠标的插入

参考 USB Linux 实现 (一) 总览

针对 hid 框架, mouse的话drivers/input/mousedev.c 的 mousedev_init 注册了 handler , 在 /dev 下创建了 /dev/input/mouse0这个handler 与drivers/hid/hid-core.c "hid_device_probe -> hid_hw_start -> hid_connect -> hidinput_connect -> input_register_device" 创建的 device 匹配[<c0105e34>] (unwind_backtrace) from [<c01047d0>] (show_stack+0x10/0x14)
[<c01047d0>] (show_stack) from [<c03ad510>] (input_register_device+0x10/0x448)
[<c03ad510>] (input_register_device) from [<c0422188>] (hidinput_connect+0x2064/0x4e8c)
[<c0422188>] (hidinput_connect) from [<c041e4e8>] (hid_connect+0x2bc/0x36c)
[<c041e4e8>] (hid_connect) from [<c041e6c8>] (hid_hw_start+0x3c/0x5c)
[<c041e6c8>] (hid_hw_start) from [<c041e920>] (hid_device_probe+0xdc/0x140)
[<c041e920>] (hid_device_probe) from [<c03630bc>] (really_probe+0x1f0/0x4cc)
[<c03630bc>] (really_probe) from [<c0363404>] (driver_probe_device+0x6c/0x1d0)
[<c0363404>] (driver_probe_device) from [<c0361878>] (bus_for_each_drv+0x54/0xb8)
[<c0361878>] (bus_for_each_drv) from [<c0363924>] (__device_attach+0xd8/0x178)
[<c0363924>] (__device_attach) from [<c0361a98>] (bus_probe_device+0x84/0x8c)
[<c0361a98>] (bus_probe_device) from [<c035fe7c>] (device_add+0x3d0/0x7c0)
[<c035fe7c>] (device_add) from [<c041eb0c>] (hid_add_device+0xec/0x2ac)
[<c041eb0c>] (hid_add_device) from [<c042a628>] (usbhid_probe+0x260/0x370)
[<c042a628>] (usbhid_probe) from [<c0395c1c>] (usb_probe_interface+0x134/0x2bc)
[<c0395c1c>] (usb_probe_interface) from [<c03630bc>] (really_probe+0x1f0/0x4cc)
[<c03630bc>] (really_probe) from [<c0363404>] (driver_probe_device+0x6c/0x1d0)
[<c0363404>] (driver_probe_device) from [<c0361878>] (bus_for_each_drv+0x54/0xb8)
[<c0361878>] (bus_for_each_drv) from [<c0363924>] (__device_attach+0xd8/0x178)
[<c0363924>] (__device_attach) from [<c0361a98>] (bus_probe_device+0x84/0x8c)
[<c0361a98>] (bus_probe_device) from [<c035fe7c>] (device_add+0x3d0/0x7c0)
[<c035fe7c>] (device_add) from [<c0393884>] (usb_set_configuration+0x484/0x868)
[<c0393884>] (usb_set_configuration) from [<c039f31c>] (usb_generic_driver_probe+0x2c/0x78)
[<c039f31c>] (usb_generic_driver_probe) from [<c0395a50>] (usb_probe_device+0x40/0xd8)
[<c0395a50>] (usb_probe_device) from [<c03630bc>] (really_probe+0x1f0/0x4cc)
[<c03630bc>] (really_probe) from [<c0363404>] (driver_probe_device+0x6c/0x1d0)
[<c0363404>] (driver_probe_device) from [<c0361878>] (bus_for_each_drv+0x54/0xb8)
[<c0361878>] (bus_for_each_drv) from [<c0363924>] (__device_attach+0xd8/0x178)
[<c0363924>] (__device_attach) from [<c0361a98>] (bus_probe_device+0x84/0x8c)
[<c0361a98>] (bus_probe_device) from [<c035fe7c>] (device_add+0x3d0/0x7c0)
[<c035fe7c>] (device_add) from [<c0387ba8>] (usb_new_device+0x1b4/0x3b0)
[<c0387ba8>] (usb_new_device) from [<c038ac7c>] (hub_event+0x780/0x16e4)
[<c038ac7c>] (hub_event) from [<c012785c>] (process_one_work+0x1d0/0x438)
[<c012785c>] (process_one_work) from [<c0127b04>] (worker_thread+0x40/0x580)
[<c0127b04>] (worker_thread) from [<c012c85c>] (kthread+0x10c/0x120)
[<c012c85c>] (kthread) from [<c0100170>] (ret_from_fork+0x14/0x24)
# cat /proc/bus/input/handlers
N: Number=0 Name=kbd
N: Number=1 Name=mousedev Minor=32
# cat /proc/bus/input/devices
I: Bus=0003 Vendor=10c4 Product=8105 Version=0111
N: Name="YSPRINGTECH USB OPTICAL MOUSE"
P: Phys=usb-s3c24xx-1/input0
S: Sysfs=/devices/platform/s3c2410-ohci/usb1/1-1/1-1:1.0/0003:10C4:8105.0002/input/input5
U: Uniq=
H: Handlers=mouse0
B: PROP=0
B: EV=17
B: KEY=1f0000 0 0 0 0 0 0 0 0
B: REL=903
B: MSC=10

USB HID 数据流相关推荐

  1. USB HID 协议

    USB HID 协议入门 转载请注明来源:cuixiaolei的技术博客 USB HID设备类的应用场合 USB HID类是USB设备的一个标准设备类,包括的设备非常多.HID类设备定义它属于人机交互 ...

  2. USB HID 设备类协议入门

    一.应用场合 USB HID类是比较大的一个类,HID类设备属于人机交互操作的设备.用于控制计算机操作的一些方面,如USB鼠标,USB键盘,USB游戏操纵杆,USB触摸板,USB轨迹球.电话拨号设备. ...

  3. STC8H开发(九): STC8H8K64U模拟USB HID外设

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  4. C++ MFC界面读写USB HID设备数据程序

    C++ MFC界面读写USB HID设备数据程序 发一个简单易用的界面,用来对USB HID设备(比如说游戏手柄,控制面板等)读写数据,一般情况下面板上有一些LED,可以帮助我们测试读写是否正确.另外 ...

  5. USB HID学习:MFC检测USB拔插事件

    MFC具备检测设备的消息,但需要手动添加.针对USB设备,需要注册对应的GUID方可.本文对此进行简单记录. 本省略对MFC机制的描述,仅描述主要的模块代码. 一.步骤 Dbt.h头文件引用 在std ...

  6. USB HID学习:数据包分析

    本文使用 Bus Hound 工具对 USB HID 设备数据包进行分析,并结合官方手册及网上文章进行整理.文中未提到的知识,建议移步参考资源. 以笔者经验,直接阅读协议无法直观理解,最好使用工具抓包 ...

  7. [转载]基于Stm32,LD3320的非特定语音识别USB HID Keyboar

    基于Stm32,LD3320的非特定语音识别USB HID Keyboard实现 ---用声音跟机器沟通 鉴于手头拥有一块ST官方的stm32f407VG discover板子以及一块ICRoute公 ...

  8. Visual Studio 2010 Win32 Usb HID 动态库创建

    一.概述 最近在项目中使用md5和sh1 算法,发现在原来的工程上,加上这两个算法的源代码竟然编译不能通过,出现100 多个bug.后来上来发现错误都是源于两个算法使用的一个头文件"StdI ...

  9. STM32 USB HID IAP升级

    找了网上大量的资料,最后发现这个东西人家还出售源码.又不是什么算法级的东西,实在理解不了. 至于为什么要用HID,不用官方的DFU,因为驱动呀,DFU识别USB的时候还是要装驱动,客户你永远理解不了他 ...

最新文章

  1. [Vert.x Core手册 for Java]-了解Vert.x
  2. 数字图像处理的就业前景
  3. virtualbox+vagrant学习-2(command cli)-20-vagrant suspend命令
  4. asc desc排序_21.数据库排序?左连接 ?右连接?
  5. 【OpenCV 例程200篇】49. 图像增强—局部直方图处理
  6. linux指令ls -1,linux命令1--ls
  7. 2020年最好用的手机是哪一款_2020年换手机不用盲目,目前这4部最值得买,好看好用性价比高...
  8. nfs 端口_Linux挂载NFS,偶发执行df命令卡顿
  9. java 抽象类命名_Java命名规范
  10. 京瓷打印机驱动安装教程,怎么安装方便点?
  11. 计算机硬盘能否做u盘用怎么用,教你怎么用移动硬盘做原系统的启动硬盘图文教程...
  12. 程序员凌晨闲暇无聊时干什么
  13. 删除IE浏览器input框自带的删除叉
  14. 各类编程语言教程合集
  15. 见山只是山 见水只是水——提升对继承的认识
  16. vscode下载安装
  17. FPGA芯片的GTX/GTH/GTY/GTP/GTZ/GTM高速信号有什么区别?
  18. Java 近期新闻:Grail 5.0、Spring、Hibernate、WildFly 及 Kotlin Multik 开发库更新
  19. 激光雷达 eai g6_如何配置TAMeb 6.0 EAI以实现复杂的身份验证要求
  20. 深入理解同步工具类,看这篇就够了

热门文章

  1. HOG特征提取原理and计算步骤,方向梯度直方图
  2. outgoing calls and incoming calls
  3. 生成open3d项目报错:error LNK2001: 无法解析的外部符号 __imp_glViewport
  4. (二)js在html中调用的三种方式
  5. java web 用户管理_Java Web(九) 用户管理系统
  6. Linux +xenomai 下sendto()系统调用过程 --WT
  7. oracle视图如何创建索引,ORACLE 创建视图索引序列
  8. Web 性能优化:HTTP
  9. appscan报告保存html,Appscan快速使用
  10. JS本地存储的方式?区别?应用?