OK, it works! This how I did it:
- Activate gpio-key devicetree overlay for each button in config.txt. I have 6 buttons configured. Each line maps a GPIO pin to a kernel keycode. Keycodes list can be found here:
https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h
/boot/config.txt
dtoverlay=gpio-key,gpio=21,active_low=1,gpio_pull=up,label=GPIO_Enter,keycode=28
dtoverlay=gpio-key,gpio=26,active_low=1,gpio_pull=up,label=GPIO_Up,keycode=103
dtoverlay=gpio-key,gpio=20,active_low=1,gpio_pull=up,label=GPIO_Down,keycode=108
dtoverlay=gpio-key,gpio=19,active_low=1,gpio_pull=up,label=GPIO_Left,keycode=105
dtoverlay=gpio-key,gpio=16,active_low=1,gpio_pull=up,label=GPIO_Right,keycode=106
dtoverlay=gpio-key,gpio=13,active_low=1,gpio_pull=up,label=GPIO_Back,keycode=158
- Create a keyboard layout file to map kernel keycodes to Android keycodes. Information about key layout files can be found here:
https://source.android.com/devices/input/key-layout-files
The list of Android keycodes is here:
https://developer.android.com/reference/android/view/KeyEvent
The filename must match the device ID (or name, but I don't know what that is, so I use IDs). The IDs I got from inspecting /proc/bus/input/devices.
/system/usr/keylayout/Vendor_0001_Product_0001_Version_0100.kl
key 28 KEYCODE_DPAD_CENTER
key 103 KEYCODE_DPAD_UP
key 108 KEYCODE_DPAD_DOWN
key 105 KEYCODE_DPAD_LEFT
key 106 KEYCODE_DPAD_RIGHT
key 158 KEYCODE_BACK
- Create init file to load gpio_keys kernel module after boot.
This step is a workaround. If there is a device overlay, the required kernel module should be automatically loaded. But it's not. I don't know why! Maybe it's a bug? Please discuss.
/system/etc/init/gpio_keys.rc
on property:sys.boot_completed=1
insmod /boot/modules/gpio_keys.ko
Have fun navigating Android with your new hardware buttons! ;-)