【usb】linux内核USB键盘驱动解析--特殊键值转化及上报
文章目录
- 一、概况
- 二、探索
- 入口
- usb_kbd_irq
- 三、总结
- 四、参考资料
一、概况
以Linux5.10内核中USB键盘驱动为例进行解析:https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.10.tar.gz
文件路径:linux-5.10/drivers/hid/usbhid/usbkbd.c
二、探索
入口
- 首先我们直接看
usb_kbd_probe这个函数的335行usb_fill_int_urb,这里是在填充USB中断传输请求。也就是说在用后面那一大堆参数填充kbd->irq这个变量。然后设置的这个传输的回调函数是usb_kbd_irq,也就是说当有键值报上来的时候,将会用usb_kbd_irq函数处理。
usb_kbd_irq
- 我们可以看到该函数的参数是一个urb(USB request block),表示本次完成传输的请求。在看117和118行,调用了函数
input_report_key向输入子系统上报键值。该函数第一个参数代表设备,第二个参数代表键值,第三个参数代表该键被按下还是释放。
for (i = 0; i < 8; i++)input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
-
第二个参数
usb_kbd_keycode[i + 224],这里的usb_kbd_keycode是一个数组,该数组用来将键盘报上来的键值,转化为输入子系统能够识别的键值。转化的原理就是usb_kbd_keycode的数组下标代表键盘报上来的键值,对应位置的值,代表转化后报给输入子系统的键值。所以这里的意思就是将键盘报上来的i+224这个键值转化为输入子系统对应的键值。 -
那么这里的
i+224又代表哪个键呢?由于i是循环变量,从0开始到7。所以i+224,其实是224~231。所以我们只需要搞清楚,224~231这几个值代表哪几个键。 -
通过查阅HID Usage Tables的第10节
10 Keyboard/Keypad Page (0x07),我们可以知道当键盘报上来04,代表字母a。如下:

-
所以我们继续查阅该表,16进制E0转换成10进制就是224,其代表左侧CTRL键。所以上面的
224~231也就是E0~E7,分别代表LeftControl,LeftShift,。。。。。。

-
我们再次回到代码里面,
usb_kbd_keycode[i + 224]意思就是将LeftControl,LeftShift,。。。。。。八个键盘报上来的键值转化为输入子系统定义的键值。 -
上面我们知道了键值转化的原理,那么我们怎么知道这个键有没有被按下呢?我们接着看
(kbd->new[0] >> i) & 1,将new[0]元素右移i位,然后在与1。啥意思?通过查阅USB HID协议8.3节,我们可以知道USB会通过一个8位的bitmap来上报CTRL,SHIFT,ALT等键。具体如下:

-
也就是说
new[0]这个unsigned char类型的变量里面的每一位代表一个键,如果这个位为0,则表示该位对应的键没有被按下;为1,则该位对应的键被按下了。每个位代表的键如上表。
三、总结
总结一下,117和118行的这个for循环,通过依次查看new[0]元素的各个位,确定该位对应的键是否被按下。并将该键值通过usb_kbd_keycode表转化为输入子系统定义的键值,后上报给输入子系统。
四、参考资料
HID Usage Tables 1.4
USB HID协议
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
