пятница, 23 июня 2017 г.

Apple Keyboard (MB110/B). Настраиваем Insert и PrintScreen под Ubuntu.

Сегодняшний пост наверное будет из серии "чем бы дитя не тешилось, лишь бы не покупало девайсы от Apple", да простят меня поклонники и многочисленные фанаты "яблочной" корпорации. Началось все с того что я решил поддаться искушению и приобрести себе клавиатуру Apple MB110/B. Не то чтобы я относил себя к числу фанатов Apple, просто работать с текстами, кодом и т.п. приходится достаточно часто, а следовательно удобство в их наборе играет важную роль. Те кто так или иначе следил за моим блогом, наверное помнит, что в свое время я купил Defender'овскую клавиатуру с "низкопрофильными" кнопками, подсветкой и прочими радостями жизни, т.к. она по-сути очень походит на клавиатуру моего ноутбука HP, которая меня максимально устраивает. Так вот, спустя несколько месяцев работы на стационарном ПК за Defender'ом я понял что она конечно напоминает ноутбучную, но достаточно отдаленно. Т.е. ход клавиш немного не тот, ощущения от нажатий и т.п. Т.е. аналог конечно, но как-то немного не тот. В поисках максимально удобной для меня клавиатуры я попробовал Apple Wired Keyboard (беспроводные просто не люблю по многим причинам) и как мне показалось - это именно то, что мне подходит. Так что я оформил заказ в DNS - и вот он, час "X" настал. Я забрал заказ, разорвал в клочья Apple'овскую коробку, которую вот в этом видео автор открывает с каким-то непонятным мне благоговейным трепетом и подключил ее к ПК.

Несколько минут знакомства с новым гаджетом подтвердили первоначальный тест - это удобно, но было несколько моментов, которые практически сводили удобство использования клавиатуры на нет, это:

  • По-умолчанию, верхний ряд кнопок F1-F12 работал не как функциональные, а как дополнительные кнопки (!), например, F1 - уменьшал яркость, F2 - увеличивал и т.п. Т.е. это были вовсе не функциональные клавиши, а дополнительные. Теперь представьте, если нам нужно нажать комбинацию кнопок Alt-F1 или Alt-F2, то приходится нажимать целых три кнопки Alt-F1-Fn или Alt-F2-Fn расположенных в разных местах, что чертовские неудобно. Я конечно понимаю, что акробатические этюды на клавиатуре в какой-то степени возможно и востребованы, но я то брал клавиатуру именно для работы, а не для освоения новых трюков. Поэтому F1-F12 мне были нужны как воздух и чтобы они нажимались без дополнительных модификаторов.
  • Отсутствие кнопки Insert ... Да, да ... на Apple'овской клавиатуре эта кнопка отсутствует в принципе (см. фото в начале статьи), открою секрет, чтобы нажать Insert нужно нажать комбинацию Fn+Enter или переключить дополнительную клавиатуру с помощью NumLock и нажать 0 на дополнительной клавиатуре. Представьте себе каково это вместо Ctrl-Insert или Shift-Insert исполнять этюд в виде Ctrl-Fn-Enter.
  • Отсутствие кнопки Prtsc / SysRq, т.е. банальный PrintScreen знакомый всем Windows пользователям на этом чуде техники отсутствует физически.
  • Ну и последнее ... расположение кнопок Ctrl-Alt-Cmd (Cmd на Mac клавиатуре - это Windows-key). Кнопки Ctrl и Cmd большие, а вот Alt находится между ними. Но лично я привык к другому порядку, Ctrl-Win-Alt, при этом Win - маленькая, а Ctrl и Alt должны быть большими. Я привык именно так и переучиваться не собирался. Поэтому в моем понимании нужно было поменять местами Alt и Cmd и тогда все стало бы на свои места.

Казалось бы всего 4 пункта в списке, но для меня они являлись существенными, без них, многие привычные и удобные вещи в работе превращались в 9-й круг ада, т.к. нажимать вместо обычного Ctrl-Ins целых три кнопки я явно не собирался. Да и реакция функциональных кнопок по-умолчанию меня совсем не устраивала. 

Первое что я решил сделать - это обратиться к официальному сайту Apple, где я нашел вот это: Изменение назначения функциональных клавиш компьютера Mac. Отлично, всего лишь одна настройка «Использовать функциональные клавиши F1, F2 и др. как стандартные» для первого пункта. Но вот незадача, у нас нет компьютера Mac, у нас даже нет MacOS, а только клавиатура Apple от которой мы хотим добиться такого же поведения. Дальнейшие поиски привели меня к следующему замечательному мануалу, вернее двум:


Автору первого руководства - отдельно спасибо. Честно говоря я не пробовал использовать Apple MB110 в Windows, но почему-то мне кажется что по написанному все пройдет достаточно гладко. Назначение функциональных клавиш в Windows определяется ключом реестра OSXFnBehavior, как видно из статьи. Однако как быть с другими ОС? И в частности моей Ubuntu 16.04? Чтобы найти ответ на этот вопрос пришлось провести еще немного времени с Google и в конечном итоге я наткнулся на мануал:


Который и послужил отправной точкой для решения всех перечисленных задач, правда с небольшими изменениями. Чтобы сделать функциональные клавиши как F1-F12 по-умолчанию в моей Ubuntu 16.04, а также, чтобы поменять местами Alt и Cmd (WinKey) я воспользовался следующими двумя командами:

sudo echo 2 | sudo tee /sys/module/hid_apple/parameters/fnmode - включение режима F1-F12 на функциональных кнопках по-умолчанию.
sudo echo 1 | sudo tee /sys/module/hid_apple/parameters/swap_opt_cmd - поменять назначение Alt и Command (Win-Key)

Честно говоря я небольшой специалист в Linux и в Ubuntu в частности, но здесь, как я понял, мы просто определяем параметры модуля hid-apple.ko (/lib/modules/4.4.0-81-generic/kernel/drivers/hid/hid-apple.ko), которые изначально предусмотрены в нем. Желающие могут погуглить про модуль ядра hid-apple и тогда все станет более ясно. После двух этих команд две озвученные проблемы были успешно решены, однако, надо было что-то делать с Insert'ом и PrintScreen'ом. И вот как раз на это у меня ушло несколько часов.

Remap кнопок с помощью xmodmap у меня работал из рук вон плохо. Т.е. если в окне терминала дать команду:

xmodmap -e "keycode 191 = Insert NoSymbol Insert NoSymbol Insert"

То remap работал, но только какое-то ограниченное время и не совсем понятно. Например мы открываем отдельное окно терминала и вводим в нем эту команду, все вроде получается. Т.е. при нажатии F13 в этом окне срабатывает Insert, однако стоит только открыть LibreOffice с помощью ярлыка на рабочем столе - то вот в нем уже почему-то F13 не работает как Insert. Также, соответствующие изменения ~/.Xmodmap с последующей перезагрузкой не привели к желаемому результату. Почитав немного многочисленные сообщения людей, которые пробовали на форуме сделать то же самое, я пришел к выводу что "это не наш метод". Т.к. среди решений было даже что-то вроде создать .desktop файл с запуском xmodmap /home/decker/.Xmodmap и поместить его в Startup Applications ... Но и этот метод не у всех работал, как его "дальнейшее развитие", люди делали bash скрипт с чем-то вроде sleep 4 && xmodmap /home/decker/.Xmodmap и все равно, когда-то это работало, а когда-то нет. С этого момента я понял что искать способ remap'а кнопок нужно на более низком уровне.

В одной из статей (было уже достаточно поздно и я читал их по диагонали), я нашел фразу, что чтобы переназначить кнопки или вообще что-то сделать с клавиатурой в Ubuntu нужно представлять каким образом вообще это работает, т.е. представлять как работает "стек драйверов" и каким образом обрабатывается нажатие по цепочке, начиная от нажатия пользователем кнопки на физическом устройстве, обработки этого нажатия драйверами и передачи соответствующего события приложению. Т.к. в Linux'е я не особенно специалист, то приведенная схема (которая по идее должна была открыть глаза на все):

hardware --scancode--> kernel --keycode--> X11 --> keysym --> application

что-то прояснила для меня, но далеко не все (да, да, я не совсем хорошо представляю как работает X11 и что происходит в ядре). Но эта статья дала очередной импульс поискам и я набрел на следующее:

Ключевой точкой был абзац из первой статьи:


Теперь рассказываю как сделал я и как я к этому пришел. Итак, мы решили назначить F13 на Insert, а F15 на PrintScreen. Что же, приступим

1. Ставим утилиту evtest через sudo apt install evtest и запускаем ее, как sudo evtest
2. В появившемся списке выбираем "Apple Inc. Apple Keyboard", у меня это было устройство /dev/input/event17. В выводе утилиты мы увидим нечто вроде:

Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x5ac product 0x250 version 0x111
Input device name: "Apple Inc. Apple Keyboard"

Нажимаем кнопку F13 чтобы определить ее KEYBOARD_KEY_%VALUE%, после нажатия F13 мы увидим:


Event: time 1498176151.012832, -------------- SYN_REPORT ------------
Event: time 1498176154.612842, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70068
Event: time 1498176154.612842, type 1 (EV_KEY), code 183 (KEY_F13), value 1
Отсюда нам нужно запомнить значение value - 70068, это шестнадцатиричное значение. Руководствуясь статьей User XKB Customization проверяем версию udev - udevadm info --ver, в моем случае результатом было 229. Таким образом теперь нам необходимо написать соответствующий файл /etc/udev/hwdb.d/98-apple-keyboard.hwdb . Но как узнать идентификатор для evdev:input? Здесь нам поможет статья How to find the .hwdb header of a general input device? .

3. Выполняем udevadm info /dev/input/event17 и запоминаем ID_VENDOR_ID, в нашем случае это 05ac. Далее делаем find /sys -name *modalias | xargs grep -i 05ac , где 05ac наш vendor_id. Ответом будут множество строк, в том числе и одна, следующего вида: 

/sys/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.2/1-11.2:1.0/0003:05AC:0250.0005/input/input20/modalias:input:b0003v05ACp0250e0111... # далее много всего

Здесь нас интересует все что находится после modalias:input до 'e', т.е. в нашем случае b0003v05ACp0250 .

4. Создаем файл /etc/udev/hwdb.d/98-apple-keyboard.hwdb от имени root и вписываем туда следующие строки:

evdev:input:b0003v05ACp0250*
 KEYBOARD_KEY_70068=insert      # F13: Insert

Обратите внимание, пробел перед KEYBOARD_KEY важен. После чего делаем:

sudo udevadm hwdb --update и sudo udevadm trigger (убедиться в том что все сработало можно сделав udevadm info /dev/input/event17 | grep KEYB , если в выводе будет что-то вроде KEYBOARD_KEY_70068=insert - значит все Ок).

5. Проверяем визуально, идем в Параметры системы -> Клавиатура -> Ввод текста и нажимаем на иконку клавиатуры под списком раскладок, у нас откроется вот такое окно:


Теперь нажимая F13 мы видим что у нас засчитывается нажатие Insert. Аналогично делаем с F15 -> PrintScreen. Здесь я приведу уже готовый вариант /etc/udev/hwdb.d/98-apple-keyboard.hwdb :

evdev:input:b0003v05ACp0250*
 KEYBOARD_KEY_70068=insert      # F13: Insert
 KEYBOARD_KEY_7006a=sysrq       # F15: PrinScr / SysRq

Вот таким нехитрым образом мы заставили работать функциональные клавиши, а также Insert и PrintScreen на клавиатуре Apple MB110/B под Ubuntu 16.04. При этом мы не использовали "плясок с бубном" вокруг отложенного запуска xmodmap, не разбирались почему не "подцепляется" наш ~/.Xmodmap, а решили проблему "уровнем ниже". И хотя в данном случае до полного понимания принципов работы и назначения udevadm и hwdb нам еще "расти и расти", поставленную задачу успешно удалось решить. Конечно, ее можно было решить и другими путями, например сборкой модифицированного hid-apple.ko (на эту тему также есть соответствующие статьи в интернете, например эта), но фраза "Macbook keyboard is painful" в самом начале как бы намекает ;) Нет, конечно, можно собрать hid-apple.ko с модифицированным / пропатченным hid-apple.c (кстати есть даже проект на Git'е), однако, для этого нужно еще качать исходники ядра, разбираться как собираются модули, а если у вас Ubuntu на системе с UEFI, как у меня, например, то еще и понимать каким образом заставить грузиться собранный неподписанный hid-apple.ko. Конечно, при наличии времени и должного энтузиазма можно сделать и это, но способ описанный мной чуть проще. Этот пост я уже писал на Apple'овской клавиатуре с работающими так, как мне нужно кнопками.

p.s. Комментарии, предложения, пожелания - приветствуются ... и да, Macbook keyboard is painful ;)

Обновлено 24.07.2017 15:56 (MSK)

Для того чтобы сделать предпочтение в работе функциональных клавиш F1-F12 описанное в статье по-умолчанию (т.е. при загрузке системы), а также поменять местами Alt и Cmd (WinKey), достаточно выполнить следующие команды:

echo options hid_apple fnmode=2 | sudo tee -a /etc/modprobe.d/hid_apple.conf
echo options hid_apple swap_opt_cmd=1 | sudo tee -a /etc/modprobe.d/hid_apple.conf
sudo update-initramfs -u -k all
sudo reboot

Обновлено 21.02.2019 23:27 (MSK)

Для Apple Magic Keyboard, которая wireless (т.е. беспроводная) последовательность действий абсолютно такая же. Только в данном случае значения будут несколько другими:

Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x5ac product 0x26c version 0x110
Input device name: "Apple Inc. Magic Keyboard with Numeric Keypad"

Как видно, изменился код product. А соответствующее значение по find /sys -name *modalias | xargs grep -i 05ac будет выглядеть следующим образом:

/sys/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.1/0003:05AC:026C.000A/input/input24/modalias:input:b0003v05ACp026Ce0110

Т.е. в /etc/udev/hwdb.d/98-apple-keyboard.hwdb мы должны прописать следующий идентификатор b0003v05ACp026C. Целиком же 98-apple-keyboard.hwdb для поддержки и проводной и беспроводной клавиатуры выглядит следующим образом:

evdev:input:b0003v05ACp0250*
 KEYBOARD_KEY_70068=insert      # F13: Insert
 KEYBOARD_KEY_7006a=sysrq       # F15: PrinScr / SysRq

evdev:input:b0003v05ACp026C*
 KEYBOARD_KEY_70068=insert      # F13: Insert
 KEYBOARD_KEY_7006a=sysrq       # F15: PrinScr / SysRq
 KEYBOARD_KEY_700e2=leftmeta    # key marked left alt -> left meta
 KEYBOARD_KEY_700e3=leftalt  # key marked left meta -> left alt

Обратите внимание, что символ перевода строки между устройствами важен. После изменения файла также нужно выполнить: sudo udevadm hwdb --update и sudo udevadm trigger

Да, обратите внимание еще на одну особенность. Почему-то рецепт для обмена местами Alt и Cmd (WinKey) рекомендованный выше и отлично работавший с проводной Apple'овской клавиатурой здесь у меня не сработал (хотя надо отметить что функциональные клавиши F1-F12 работали как именно F1-F12 по-умолчанию, с использованием рекомендаций из основной статьи). Поэтому для решения данной проблемы я также применил low-level key remapping. В результате левый Option (700e2) на Mac'овской беспроводной клавиатуре у меня работает как Command / Meta / Win, а левый Command (700e3) как левый Alt. Впрочем в комментариях получившегося 98-apple-keyboard.hwdb - это описано.

Также, в рассматриваемом примере клавиатура была подключена к ПК посредством комплектного Lightning/USB кабеля. С беспроводным подключением разбираться пока не стал, т.к. на текущий момент для меня достаточно обычного проводного подключения. А, собственно, беспроводная версия клавиатуры бралась исключительно по причине отсутствия в продаже проводных.

p.s. Да, ну и пока я писал это небольшое дополнение, наткнулся на еще одно небольшое руководство с примерами - Linux udev keys binding, возможно для кого-то окажется полезным.

Для того чтобы запустить проверку корректности переназначения кнопок (аналог меню Параметры системы -> Клавиатура -> Ввод текста в Ubuntu 16.x) в Ubuntu 18.x достаточно набрать в терминале gkbd-keyboard-display -l us , т.к. как вызвать это приложение в 18.x из настроек системы для меня честно говоря до сих пор не очевидно.

p.p.s. Ну и совсем последний постскриптум к этой части. Наверняка многие задались вопросом, а откуда собственно взять "названия кнопок" для mapping'а, т.е. где можно посмотреть возможные значения вроде insert, sysrq, leftmeta, leftalt и т.п. В этом вам может помочь следующее: Where is “keyboard-keys-from-name.h” used by udev of systemd of Linux? , keyboard-keys-from-name.h . Ну и как говорится по первой ссылке - не лишним будет заглянуть в /usr/include/linux/input-event-codes.h .

Комментариев нет :

Отправить комментарий