Mengonfigurasi shortcut pada level Window Manager (X11/Wayland) atau IDE sering kali gagal ketika tombol periferal mengirimkan scancode non-standar atau tidak dikenali oleh kernel. Melakukan remapping pada subsistem input Linux via udev dan hwdb (Hardware Database) memastikan translasi scancode ke keycode terjadi sebelum event mencapai display server. Pendekatan ini menghasilkan pemetaan yang konsisten di terminal TTY, Wayland, X11, maupun container lokal.

Arsitektur Input Linux: Scancode vs Keycode

Saat tombol keyboard ditekan, controller hardware mengirimkan scancode mentah ke driver kernel. Subsistem input kernel Linux (evdev) kemudian menerjemahkan scancode tersebut menjadi keycode standar Linux yang didefinisikan di <linux/input-event-codes.h>. Display server (seperti Xorg atau Wayland compositor) membaca keycode ini lalu menerjemahkannya kembali menjadi keysym via XKB.

Jika hardware Anda memiliki tombol Fn/Media yang mati atau mengirim keycode yang tidak berguna (misalnya KEY_PROG1 atau scancode tanpa binding), memperbaikinya di layer XKB tidak efisien. Solusi paling stabil untuk Developer Experience (DX) adalah memetakan scancode langsung ke keycode fungsional pada layer udev/hwdb.

Langkah 1: Mengidentifikasi Scancode Menggunakan evtest

Langkah pertama adalah membaca scancode mentah langsung dari device node menggunakan tool evtest. Buka terminal root atau gunakan sudo:

sudo apt install evtest   # Debian/Ubuntu
sudo pacman -S evtest     # Arch Linux
sudo evtest

Pilih event device keyboard Anda dari daftar yang muncul. Tekan tombol yang ingin dimodifikasi. Output akan menampilkan event input serupa berikut:

Event: time 1710582001.123456, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70068
Event: time 1710582001.123456, type 1 (EV_KEY), code 148 (KEY_PROG1), value 1
Event: time 1710582001.200000, type 1 (EV_KEY), code 148 (KEY_PROG1), value 0

Catat nilai MSC_SCAN (contoh di atas: 70068 atau dalam format hex lain seperti c022d). Nilai inilah scancode hardware yang akan dipetakan ulang. Jika tombol sama sekali tidak memicu event EV_MSC, tombol tersebut ditangani sepenuhnya oleh firmware/EC (Embedded Controller) laptop dan tidak dapat dimapping oleh OS.

Langkah 2: Menentukan Match Device ID

Aturan hwdb membutuhkan string identifikasi device yang akurat. Ambil string identifikasi dari device node keyboard Anda (misal /dev/input/event3) menggunakan udevadm:

udevadm info /dev/input/event3 | grep -E "ID_BUS|ID_VENDOR_ID|ID_MODEL_ID|MODALIAS"

Alternatif lazier: buat rule generik yang menargetkan semua keyboard AT atau USB standar menggunakan prefix modalias bus input:

  • Keyboard internal laptop (AT keyboard): evdev:atkbd:dmi:*
  • Keyboard USB umum: evdev:input:b0003v*p*
  • Semua keyboard input device: evdev:name:*

Langkah 3: Konfigurasi File hwdb

Buat file baru di direktori /etc/udev/hwdb.d/. Jangan modifikasi file di /usr/lib/udev/hwdb.d/ karena file tersebut akan tertimpa saat update sistem.

sudo nano /etc/udev/hwdb.d/90-custom-keyboard.hwdb

Tulis konfigurasi mapping. Penting: Baris aturan pencocokan tidak boleh diawali spasi, sedangkan baris konfigurasi mapping (KEYBOARD_KEY_...) wajib diawali tepat satu karakter spasi (ASCII space).

# Mapping tombol internal laptop / AT keyboard
evdev:atkbd:dmi:*
 KEYBOARD_KEY_70068=leftctrl
 KEYBOARD_KEY_c022d=f13

# Mapping keyboard eksternal via USB Vendor/Product ID
evdev:input:b0003v046DpC31C*
 KEYBOARD_KEY_70039=capslock
 KEYBOARD_KEY_7003a=leftctrl

Nilai keycode target harus ditulis dalam huruf kecil (misal: leftctrl, f13, f14, mute, playpause) sesuai definisi di kernel driver tanpa prefix KEY_. Menggunakan F13 hingga F24 merupakan pola DX terbaik untuk binding shortcut IDE/Window Manager (misal: i3, sway, Hyprland, Neovim) karena key tersebut tidak bertabrakan dengan kombinasi tombol standar.

Langkah 4: Kompilasi dan Reload hwdb Tanpa Restart

Setelah file disimpan, compile database biner hwdb dan trigger update pada subsistem udev tanpa perlu melakukan reboot OS:

# 1. Kompilasi hwdb binary ke /etc/udev/hwdb.bin
sudo systemd-hwdb update

# 2. Trigger hardware event untuk memperbarui tabel keycode
sudo udevadm trigger --verbose --subsystem-match=input --action=change

Uji kembali menggunakan evtest. Sekarang scancode target harus menghasilkan nilai EV_KEY yang baru didefinisikan.

Fallback Cepat: setkeycodes

Jika Anda membutuhkan pengujian sementara tanpa menulis file konfigurasi permanen atau bekerja pada sistem tanpa systemd/udev, gunakan utility setkeycodes bawaan package kbd:

# Format: sudo setkeycodes <scancode_hex> <keycode_int>
# Keycode 29 = KEY_LEFTCTRL (dilihat dari /usr/include/linux/input-event-codes.h)
sudo setkeycodes 70068 29

Kelemahan setkeycodes: konfigurasi bersifat temporer (hilang saat reboot) dan hanya bekerja untuk keyboard pada bus AT/PS2 (driver atkbd), tidak mendukung keyboard USB HID modern.

Troubleshooting Masalah Umum

  • Indentasi Salah: Parser systemd-hwdb sangat ketat. Baris KEYBOARD_KEY_... yang tidak diawali spasi tunggal akan diabaikan secara diam-diam tanpa pesan error eksplisit.
  • Nilai Scancode Hex vs Desimal: evtest mencetak nilai hex atau desimal. Nilai KEYBOARD_KEY_<hex> pada hwdb selalu membutuhkan representasi hexadesimal tanpa prefix 0x. Jika evtest mencetak value desimal murni, konversikan terlebih dahulu ke hex.
  • Filter Modalias Terlalu Spesifik: Jika rule tidak terpicu, longgarkan string pencocokan menjadi evdev:input:b* selama proses debugging.