Изменение назначения клавиш модификаторов. Патчим ядро Linux

Решил переназначить клавиши на клавиатуре по следующей схеме:

Caps Lock -> Shift 
Shift -> Caps Lock

LCtrl -> LWin 
LWin -> LAlt 
LAlt -> LCtrl

RCtrl -> RWin 
RWin -> RAlt 
RAlt -> RCtrl

Основная сложность заключалась в том, что должно работать везде. Не в какой-то одной программе, не в какой-то одной одной оконной системе. Хотелось чтобы работало везде, как в голом терминале без X сервера, так и в графическом окружении. Универсального решения в таком случае нет и нужно писать несколько конфигурационных файлов. Я честно попытался, но мои потуги не привели к желанному результату. В итоге, решил залезть в ядро Linux, ибо другие способы не прижились.

Коды клавиш можно найти в include/linux/input.h

Результат:

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 78d2499..de03463 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -431,6 +431,35 @@ void input_event(struct input_dev *dev,
 {
 	unsigned long flags;
 
+	if (type == EV_KEY) {
+		switch (code) {
+		case KEY_CAPSLOCK:
+			code = KEY_LEFTSHIFT;
+			break;
+		case KEY_LEFTSHIFT:
+			code = KEY_CAPSLOCK;
+			break;
+		case KEY_LEFTALT:
+			code = KEY_LEFTCTRL;
+			break;
+		case KEY_RIGHTALT:
+			code = KEY_RIGHTCTRL;
+			break;
+		case KEY_LEFTMETA:
+			code = KEY_LEFTALT;
+			break;
+		case KEY_RIGHTMETA:
+			code = KEY_RIGHTALT;
+			break;
+		case KEY_RIGHTCTRL:
+			code = KEY_RIGHTMETA;
+			break;
+		case KEY_LEFTCTRL:
+			code = KEY_LEFTMETA;
+			break;
+		}
+	}
+
 	if (is_event_supported(type, dev->evbit, EV_MAX)) {
 
 		spin_lock_irqsave(&dev->event_lock, flags);

Узнать, какой код соответствует нажатой клавише можно, если заменить switch в патче на:

pr_info("KEY:%u\n", code);

Коды в таком случае отображаются в логе ядра.

Пост перенесён из старого блога, патч обновлён до ядра 4.2.6.

Продолжение без издевательств над ядром.

Comments

comments powered by Disqus