Клавише соответствуют символы на трёх уровнях: scancode, keycode и keysym.
Scancode - обычно зависит от харда и поменять его нельзя.
Keycode - назначается по вкусу.
Keysym - собственно символ, в зависимости от раскладки, Shift и т.д.

Одному keycode соответствуют разные keysym.

Такие сложности нужны, чтобы, с одной стороны, можно было поменять местами клавиши (уровень scancode -> keycode), а с другой - создать раскладку клавиатуры (англ, ру и т.д.) (уровень keycode -> keysym).
Например, поменяем Shift и CapsLock (из-под рута):
setkeycodes 2a 58
setkeycodes 3a 42


и вернём на место:
setkeycodes 2a 42
setkeycodes 3a 58


Если ядро не слышит scancode, что либо сделать затруднительно. У меня 2.6.17 ядро не слышало, например, четырёх "специальных" кнопок.
Но 2.6.22 уже поддерживало всё, что надо. Кстати, у меня ядро (2.6.27) кнопки, включающие bluetooth, 3G, WLAN слышатся ядром - можно бы на них какой-то символ повесить :) Между прочим, кнопка Power тоже генерирует scancode (0xe05e), которому соответствует keycode 116.


Если ядро слышит scancode, но не знает, какой keycode ему
соответствует, оно пишет на консоль что-то типа
[ 845.109638] atkbd.c: Unknown key pressed (translated set 2, code 0xb3 on isa0060/serio0).
[ 845.109793] atkbd.c: Use 'setkeycodes e033 ' to make it known.
[ 845.208315] atkbd.c: Unknown key released (translated set 2, code 0xb3 on isa0060/serio0).
[ 845.208466] atkbd.c: Use 'setkeycodes e033 ' to make it known.
Надпись может не появляться из-за выставленного console debug level.

Любопытная информация содержится в /usr/include/linux/input.h:
#define KEY_RESERVED 0
#define KEY_ESC 1
#define KEY_1 2
#define KEY_2 3
#define KEY_3 4
#define KEY_4 5
...
#define KEY_MAX 0x1ff
#define KEY_CNT (KEY_MAX+1)

Теперь практика.

setkeycodes ставит в соответствие scancode -> keycode. Если keycode не назначен, то ни в консоли, ни в Иксах клавиша
работать не будет. Чтобы узнать scancode, используется showkey -s;
для keycode - showkey. Обе команды работают под консолью. Рисковые могут попробовать то же под Иксами в терминале.
Под Иксами keycode показывает xev. Но почему-то keycode в Иксах и консоли различаются (я не понял по какому принципу хотя "лопатил" исходники), причём соответствие между keycode #x в Иксах и #y в консоли взаимнооднозначное, и если keycode в консоли не назначен, то в Иксах клавиша не будет видна из xev. Любопытно, что если назначить в консоли keycode >= KEY_UNKNOWN=240, то в Иксах клавиша опять-таки не будет видна из xev.

Соответствие keycode -> keysym настраивается так.
Иксы:
cat > .xmodmap < f <
keymaps 0-15
keycode 120 = U+0454 U+0404
keycode 121 = U+0457 U+0407
EOF
loadkeys f

Существенно, что файл для loadkeys начинается с keymaps 0-15.
Подробности - в мануале.

В консоли на клавишу можно вешать не только символ, но и строку символов.
У меня, например, € и $ генерировали #ifdef, #define...
Вот выдержка из man loadkeys:
The kernel string table is a sequence of strings
with names like F31. One can make function key F5 (on
an ordinary PC keyboard) produce the text `Hello!',
and Shift+F5 `Goodbye!' using lines


keycode 63 = F70 F71
string F70 = "Hello!"
string F71 = "Goodbye!"


Как я понимаю, HAL следит в том числе за нажатиями клавиш и поэтому может запускать программы, назначенные на определенные события. Задача только в том, чтобы найти прогу и повесить ее на событие.

2 коммент.:

Если при нажатии сочетания клавиши не выводиться scankey, пытаюсь настроить клавишу "Fn" Есть варианты? Что можно сделать? Клавиши рабочие.

28 октября 2012 г., 14:39  

Отличная статья, узнал много из того, что искал.
Только проблемка возникает в дебиане: при назначении setkeycodes и перезагрузки системы, все назначенные клавиши слетают...Решения так и не нашел :\

3 мая 2015 г., 22:32  

Следующее Предыдущее Главная страница