[BUG]an input device can not support more than 568 keys due to uevent buffer too small
From: Zhai Zhaoxuan <hidden>
Date: 2021-03-13 06:33:57
Hi Dmitry and Greg, I recently started making a keyboard utility. It basically helps the user press some keys based on a user script. So I tried to use the "uinput" driver to help me send keys to the kernel. Due to any key and combination can be requested by the user script, I tried to enable all KEYBIT on the uinput device. But it fails. And more accurate, using a binary search, it seems that I am unable to enable more than 568 keys. The KEY_MAX (defined in linux/input-event-codes.h) is 0x2ff. So it should be ok to enable 767 keys. The uinput device should not fail with only 568 keys. I read system logs. The log shows that the new input device fails due to systemd-udevd trying to read `/sys/devices/virtual/input/input4/uevent`, but this file is empty unexpectedly. Then ,I searched on the web about this and found a bug opened in 2016-05-24 by Markus: https://bugzilla.kernel.org/show_bug.cgi?id=118861 The status of this bug is still NEW. I tried to debug the kernel. And I got something that may be useful. The "uevent" shows empty, because a -ENOMEM error returns by `input_add_uevent_modalias_var`. And this function returns -ENOMEM, because the `buf` on `struct kobj_uevent_env` is not enough. The size of `buf` is 2048 (UEVENT_BUFFER_SIZE). According to the MODALIAS encoding algorithm (input_print_modalias_bits), if we allow all 0x2ff keys to be enabled on the uinput device, the buffer should have at least 2477 bytes. (2477 = 3 * (0xff - 0x71 + 1) + 4 * 0x200) 2048 is smaller than 2477, so it fails. I have tried to set UEVENT_BUFFER_SIZE to 4096. After that, everythings seems ok. The `/sys/devices/virtual/input/input4/uevent` can show its content correctly. (See the attachment uevent.txt) Since this change is related to the core feature kobject which is used everywhere in the kernel, I don't know if doubling the UEVENT_BUFFER_SIZE is the best way to fix it, or if it will cause other serious problems. Or maybe we can use a dynamic buffer size in `struct kobj_uevent_env`. Thank you, Zhai Zhaoxuan