Article directory
1. Overview
Take the USB keyboard driver in the Linux5.10 kernel as an example to analyze: https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.10.tar.gz
file path:linux-5.10/drivers/hid/usbhid/usbkbd.c
Two, explore
Entrance
- First, let's look directly at
usb_kbd_probe
line 335 of this functionusb_fill_int_urb
, where the USB interrupt transfer request is filled. That is to say, this variable is filled with a lot of parameters laterkbd->irq
. Then set the callback function of this transmissionusb_kbd_irq
, that is to say, when a key value is reported, it will beusb_kbd_irq
processed with a function.
usb_kbd_irq
- We can see that the parameter of this function is a urb (USB request block), indicating the request to complete the transfer this time. Looking at lines 117 and 118, the function is called
input_report_key
to report the key value to the input subsystem. The first parameter of this function represents the device, the second parameter represents the key value, and the third parameter represents whether the key is pressed or released.
for (i = 0; i < 8; i++)
input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
-
The second parameter
usb_kbd_keycode[i + 224]
, hereusb_kbd_keycode
is an array, which is used to convert the key value reported by the keyboard into a key value that the input subsystem can recognize . The principle of conversion is thatusb_kbd_keycode
the subscript of the array represents the key value reported by the keyboard, and the value of the corresponding position represents the key value reported to the input subsystem after conversion. So the meaning here is toi+224
convert the key value reported by the keyboard into the corresponding key value of the input subsystem. -
So which key does this
i+224
represent? Since i is a loop variable, it starts from 0 to 7. So i+224 is actually 224~231. So we just need to figure out224~231
which keys these values represent. -
By referring to Section 10 of HID Usage Tables
10 Keyboard/Keypad Page (0x07)
, we can know that when the keyboard reports 04, it represents the letter a. as follows:
-
So we continue to look up the table, and the conversion of hexadecimal E0 to decimal is 224, which represents the left CTRL key. So the above
224~231
is, respectivelyE0~E7
, representLeftControl
,LeftShift
,. . . . . .
-
Let's go back to the code again,
usb_kbd_keycode[i + 224]
which means willLeftControl
,LeftShift
,. . . . . . The key values reported by the eight keyboards are converted into key values defined by the input subsystem. -
Above we know the principle of key-value conversion, so how do we know whether this key has been pressed? Let's see next
(kbd->new[0] >> i) & 1
, shift the new[0] element to the right by i bits, and then add 1. What do you mean? By referring to Section 8.3 of the USB HID protocol , we can know that the USB will report CTRL, SHIFT, ALT and other keys through an 8-bit bitmap. details as follows:
-
That is to say, each bit in this type of variable represents a key. If this bit is 0, it means that the key corresponding to this bit has not been pressed; if it is 1, then the key corresponding to this bit has been pressed
new[0]
.unsigned char
The key represented by each bit is as in the table above.
3. Summary
To sum up, the for loop in lines 117 and 118 checks each bit of the new[0] element in turn to determine whether the key corresponding to the bit is pressed. And the key value is converted into the key value defined by the input subsystem through the usb_kbd_keycode table, and then reported to the input subsystem.