Настройка Asus AcerEEE PC Fn+F7

Это заметка, но, быть может, кому-то и поможет. Должен сразу заметить, что после установки на оный нетбук (Acer EEE PC 1005 PXD) почти все Fn'ки заработали сразу, за исключением Fn+F7 (на остальные мне удалось навесить хоткеи). Начало раскопок было, как водится, трудным: пришлось перечитать кучу манов, вики и вообще много буковок перебрать (в т.ч. на аглицком), прежде чем я смог понять вообще куда копать. Вначале, нужно начать с того, что в нашей вики весь процесс описывается довольно сдержанно, но хотя бы показывает дорогу. Вообще, было интересно копать от модулей клавиатуры ядра atkbd до xinput, и выяснить в итоге, что иксы не обрабатывают клавиши с кейкодами выше 255. Далее вопрос возник сам собой: а как «заставить» понимать иксы клавишу с кейкодом(keycode) 431(dec)? Из этого я узнал, что в моём Арчике существует овер 9000 слоёв абстракции, то бишь, имеем: ядерный уровень, — как правило, обрабатывает сканкод(scancode) и присваивает определённое число — кейкод(keycode); затем, — в зависимости от присвоенного значения — выполняет действия на поступившее событие (тогда я ещё не знал, что событиями от клавиатуры управляет тот же udev). Затем, данное значение передаётся дальше, т.е. иксам. Иксы данное значение просто «не видят». В итоге, в течение долгого, несколькодневного пытания настроить клавишу Fn+F7 перебрал кучу способов, как то: поставить пакет evrouter — он как бы пробрасывает кейкоды, которые выше 255 на уровень ниже; например, можно пробросить кейкод 431 на более низкий, например, 253. Но этот способ мне не понравился, т.к. это требовало запускать отдельный демон, писать к нему сервис запуска с аргументами и вообще... есть и другие способы. Дальше мне пришла идея поискать патчи на сами иксы (ну, неужели у меня одного так?), и, таки, патч нашёлся! Дело в том, что в иксах за приём событий от ядра отвечает модуль xf86-evdev. Естественно, добрые люди его уже догадались пропатчить. Но и это меня не устроило :-) (модуль загружался и даже делал своё дело, но мне хотелось решить это штатными средствами, т.к. данный модуль давно не обновлялся и обновлять это мне потом придётся вручную). И тут я добрался до udev'а. До этого момента дела у меня с ним не ладились: я не мог понять как с ним обращаться; но после долгого чтения, вникания и экспериментов, мне удалось заставить его пробрасывать события сочетания через создаваемый им /dev/input/event* EEE Pc WMI Hotkeys — хотфикс для разных ноутбучных клавиатур. Я добавил свой сканкод клавиши, узнать который можно не только через showkey (который в иксах не хочет работать, а xev не видит сочетание, т.к. сам работает через иксы), а и через кошерный evtest, и попросил ядро через правило udev присвоить сканкоду клавиши e9 кейкод равный значению display_off(245)
Пробуем выполнить его от рута, т.к. доступ к устройствам /dev/input/event* есть только у рута.

$sudo evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:      Lid Switch
/dev/input/event1:      Sleep Button
/dev/input/event2:      Power Button
/dev/input/event3:      Power Button
/dev/input/event4:      Video Bus
/dev/input/event5:      AT Translated Set 2 keyboard
/dev/input/event6:      PC Speaker
/dev/input/event7:      Eee PC WMI hotkeys
/dev/input/event8:      HDA Intel Headphone Mic
/dev/input/event9:      USB 2.0 UVC VGA WebCam
/dev/input/event10:     ETPS/2 Elantech Touchpad
Select the device event number [0-10]: 7
Input driver version is 1.0.1
Input device ID: bus 0x19 vendor 0x0 product 0x0 version 0x0
Input device name: "Eee PC WMI hotkeys"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 1 (KEY_ESC)
    Event code 113 (KEY_MUTE)
    Event code 114 (KEY_VOLUMEDOWN)
    Event code 115 (KEY_VOLUMEUP)
    Event code 139 (KEY_MENU)
    Event code 148 (KEY_PROG1)
    Event code 152 (KEY_SCREENLOCK)
    Event code 171 (KEY_CONFIG)
    Event code 172 (KEY_HOMEPAGE)
    Event code 184 (KEY_F14)
    Event code 185 (KEY_F15)
    Event code 191 (KEY_F21)
    Event code 212 (KEY_CAMERA)
    Event code 224 (KEY_BRIGHTNESSDOWN)
    Event code 225 (KEY_BRIGHTNESSUP)
    Event code 227 (KEY_SWITCHVIDEOMODE)
    Event code 238 (KEY_WLAN)
    Event code 240 (KEY_UNKNOWN)
    Event code 431 (KEY_DISPLAYTOGGLE)
    Event code 533 (KEY_CAMERA_ZOOMIN)
    Event code 534 (KEY_CAMERA_ZOOMOUT)
    Event code 535 (KEY_CAMERA_UP)
    Event code 536 (KEY_CAMERA_DOWN)
    Event code 537 (KEY_CAMERA_LEFT)
    Event code 538 (KEY_CAMERA_RIGHT)
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
Key repeat handling:
  Repeat type 20 (EV_REP)
    Repeat code 0 (REP_DELAY)
      Value    250
    Repeat code 1 (REP_PERIOD)
      Value     33
Properties:
Testing ... (interrupt to exit)
Пробуем нажать нашу комбинацию:

Event: time 1412394050.771966, type 4 (EV_MSC), code 4 (MSC_SCAN), value e9
Event: time 1412394050.771966, type 1 (EV_KEY), code 431 (KEY_DISPLAYTOGGLE), value 1
Event: time 1412394050.771966, -------------- EV_SYN ------------
Event: time 1412394050.772016, type 1 (EV_KEY), code 431 (KEY_DISPLAYTOGGLE), value 0
Event: time 1412394050.772016, -------------- EV_SYN ------------
Итак, evtest мне показал, что сканкод моей клавиши e9(hex), и что ядро его обрабатывает и присваивает кейкод 431(dec). Лезем в /usr/include/linux/input.h (не забудьте перевести десятичное число в шестнадцатеричное) и видим, что за этим номером у нас как раз обработка, внезапно, displaytoggle, но ядро по каким-то причинам не гасит экран (проверял в консоли, т.к. через иксы это должно выполняться по-другому). Ну и ладно, переназначим на своё событие. Лезем в /usr/lib/udev/hwdb.d — это база данных и правила как обращаться udev'у с различным оборудованием. Находим там базу данных клавиатур и заглянем в неё. Как мы помним evtest выдал нам сканкод клавиши за номером e9. Поиск по данному сканкоду нам ничего не даёт. Что ж, добавим! Да только не в этот файл, ибо он перепишется при обновлении, а создадим в каталоге /etc/udev/hwdb.d/ свой файл с названием 70-keyboad.hwdb и добавим туда новую секцию (файл /usr/lib/udev/hwdb.d можно использовать как шаблон):

###########################################################
# Asus
###########################################################

#From systemd 220 the udev ABI changed.
#keyboard:dmi:bvn*:bvr*:bd*:svnASUS:pn*
#keyboard:name:Eee PC WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr*

evdev:name:Eee PC WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr*
 KEYBOARD_KEY_e9=display_off
где KEYBOARD_KEY_* — добавляемое правило для определённого сканкода, а e9 — значение сканкода, который нам показал evtest. Т.к. значение display_off на порядок ниже — 245 (см. /usr/include/linux/input.h), то иксы должны его воспринять.
Итак, перекомпилируем базу данных
$sudo udevadm hwdb --update
Теперь перезагрузим компьютер, т.к. перезагрузка правил udevadm trigger работает лишь для вновь добавляемых правил, в то время, как изменение уже используемых (/dev/input/event7 уже используется) требует перезагрузки. Итак, по идее, теперь udev обрабатывает события сканкода и отправляет его ядру, которое в свою очередь обрабатывает его, присваивает кейкод по правилам udev'а иотправляет его дальше, а именно иксам, вот такая вот бюрократия! Запускаем наш xev и видим, что событие приходит, но для него не назначено никакого символа. Конечно, ведь иксы тоже бюрократичны и там тоже имеется, как минимум, два слоя, прежде, чем событие дойдёт до самого́ приложения. Из xev'а узнаё́м keycode (у меня он был 253). Затем открываем файл /usr/share/X11/xkb/symbols/inet и ищем там строчку с описанием нашего keycode. У меня она оказалась за номером I253 и закомментированной. Что ж, раскомментируем и присвоим ей какое-либо существующее значение, например, XF86LaunchA (полный список значений доступен по адресу /usr/include/X11/XF86keysym.h). Далее, прописываем куда-нибудь в автозапуск скрипт отключения экрана и вешаем на него хоткей. В кедах это можно сделать штатно через «Параметры системы → Комбинации клавиш и росчерки → раздел Специальные действия → правым кликом мыши по списку действий → Новый → Глобальная комбинация клавиш → Команда или адрес.» Далее, во вкладке Активация задаём наш вновь созданный хоткей, а во вкладке Действие вводим команду
/bin/xset -display :0 dpms force off
Сохраняем свою работу и перезагружаем иксы. Т.к. у меня KDE, то я перезагружаю их командой
$sudo systemctl restart kdm
для гнома kdm, соответственно, нужно заменить на gdm.
====================================================
В блог не решился поместить, т.к. для блога заметка не викифицирована и написана, что называется, от себя. Сильно не пинайте — это моя первая заметка; если у кого есть предложения по улучшению — всегда готов вычитать :-)
P.S.: Обновлено правило udev'а, т.к., начиная с версии 220 systemd, ABI udev'а было изменено.
[email protected]# cat /dev/ass > /dev/head
Нормальная заметка. Я бы ее все равно в блоги поместил. Если надумаете - маякните, перенесу.
Заметку обновил, уточнил модель нетбука, подправил правило udev'а (признаюсь, согрешил: делал ночью и добавил правило к уже существующим :-), а при создании нового правила, путём копипаста с моей же заметки вылезла ошибка: оказывается, между описанием правила и самим правилом не должно быть пустых строк...).
Теперь, у меня главный вопрос знатокам: почему ядро не обрабатывает сразу это событие? В /usr/include/linux/input.h ясно прописано же, что этой комбинации соответвствует отключение подсветки дисплея ( строка 635 явно намекает нам на это: #define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */ ). В установочном LiveCD ядро каким-то образом отключает подсветку монитора через определённое время, значит, такая возможность у него есть, как её включить в штатном ядре? Если это событие ACPI, то как можно ими управлять, не устанавливая демон (не хочется лишнего демона для одного только управления подсветкой); может, посылкой сигнала в какой-нибудь /proc/sys etc?..
P.S.: Если заметка соответствует критериям блога, то можете переместить.
[email protected]# cat /dev/ass > /dev/head
Это первая заметка о переназначении клавиш. Похвально.
Попробую внести некоторые дополнения и уточнения из своей практики
- showkey в иксах работает, но нужно через sudo — правда это делать не рекомендуется, а бывает и так, что scancode в иксах и консоли отличаются.
- showkey показывает только те scancode, которые известны ядру и пропускает scancode посылаемые клавиатурой. Чтобы это исключить, нужно загрузиться с опцией ядра atkbd.softraw=0, что переключает ядро в режим native scancode.
Из своей практики хочу добавить, что эта опция частенько изменяет все scancode. Также хотелось бы отметить, что частенько showkey показывают совсем не те scancode — отличаются, как правило, на 8.
- xev — как правило толку от нее мало при ремонте мультимедийных клавиш
- evtest — считаю одной из лучших утилит.
Насчет задействования мультимедийных клавиш - scancode является самым нижним уровнем идентификации клавиши, определен на аппаратном уровне, и вообщем то он определен всегда. Как правило, цепочка рвется на уровне keycode --- keysym, а поэтому знание scancode не так и важно (за исключением редких случаев). Это я к тому, что нужно вначале пробовать восстановить эту цепочку, а использовать для этого лучше наиболее простые способы — утилиты setkeycodes и xmodmap, что намного проще и удобнее, но это дело вкуса.
Для получения информации о keycode + keysym + keysumname (чтение текущей конфигурации XKB) лучше использовать
$ xmodmap -pke
$ xkbcomp -xkb :0 -
Ошибки не исчезают с опытом - они просто умнеют
можно ли повесить на клавишу скрипт, чтобы он работал и в консоли и в иксах?
такие дела.
vasek, всё бы хорошо, я бы и сам был бы рад через xkb настроить, но, как я уже написал, иксы не обрабатывают «сканкод» выше 255, вот и приходится плясать с бубном. А про xkb самая кошерная статья у Ивана Паскаля. Здесь был вопрос в другом: ядро-то мою клавишу как раз и обрабатывает (что доказывает номер клавиши (keycode) - 431, если бы было необработано, то в dmesg сыпались бы ошибки, а код был бы шестнадцатеричным), но не отрабатывает событие. А в иксах showkey отличается потому, что, ещё раз повторюсь, — иксы обрабатывают код(keycode) клавиши который присваивается ядром, а приложениям иксы посылает уже обработанный символ(keysym); showkey через sudo в иксах такое же приложение, не более, и, поэтому, на вход оно получает другой «сканкод»(т.е. обработанный иксами keysym), и именно поэтому его и не рекомендуют запускать в иксах, т.к. сканкод не сырой, а дважды обработанный: сначала ядром, затем иксами. Xev же показывает, назначен ли keysym на определённый код и, если не назначен, то выводит nosymbol, т.к. иксы могут воспринимать клавишу, но в таблице ей может быть не назначен keysym(если интересно, загляните в /usr/share/X11/xkb/symbols/inet — вы удивитесь сколько сочетаний и клавиш остаются необработанными, в заметке я это, кстати, ммм... заметил :-). То есть, у меня цепочка рвалась как раз в месте ядро → иксы, т.к. ядро присвоило кейкод(keycode) (не сканкод!) 431(dec) клавише, у которой сканкод равен e9(hex), т.е. кейкод (в дальнейшем я буду просто писать код) 431(dec) выше кода 255(dec). Вы должны понимать, что иксы получают не голый необработанный сканкод клавиши, но её номер - кейкод, присвоенный ей ядром, что правило udev'а и доказывает (ведь udev — это просто набор правил, по которым играет ядро, то я просто попросил ядро присвоить код(keycode) клавише со сканкодом e9 пониже, скажем, 253). Т.е. до иксов доходит уже обработанная клавиша (по идее, ядро должно было отработать и событие, которое навешено на него, но, как говорится, должно, но не обязано :-)), а далее иксы уже обрабатывают код(keycode) клавиши по-своему, а приложению выдают готовый символ keysym(-bol), например XF86BrightnessUP, или Cyrillic_GHE, и т.д. Это всё работа xkb. Итог: получается цепочка: физический сканкод(scancode) с порта клавиатуры → получение его драйвером atkbd и дальнейшая передача этого кода(scancode) ядру → обработка клавиши(scancode) ядром по правилам udev'а; если сканкод известен, то присвоение номера кода(keycode) клавише и дальнейшая передача его(keycode) приложениям, в данном случае иксам → получение входящего кода(keycode) клавиши иксами через evdev и передача его(keycode) модулю xkb → обработка кода(keycode) модулем xkb и назначение ему символа(keysym) (в зависимости от номера кода клавиши(keycode), которое прислало ядро), и передача этого символа(keysym) приложениям. Т.е. сам низкоуровневый сканкод (scancode) клавиши, тот, что e9(hex) фигурирует лишь на уровне драйвера клавиатуры ядра, после него мы можем лишь оперировать кодом(keycode) клавиши, которое присваивает ядро (которое играет по правилам udev'а 8-). Я читал вики до просветления и опыты это доказывают :-)) Если неверно, поправьте, пожалуйста :-)
xmodmap -pke - это лишь многомерная таблица сопоставления символов(keysym) кодам(keycode)(те, что присвоены ядром) клавиш. Она высокоуровневая по отношению к ядру. Драйвер xkb получает коды клавиш от ядра, а ядро играет по правилам udev'а. Я через правила udev'а смогу всю таблицу переписать ;-))
P.S.: Главный вопрос остаётся в силе: почему ядро не обрабатывает событие?

P.P.S.: cucullus, можно, если вы возьмёте код(keycode) клавиши или сочетания, который одинаков везде и через правило udev зададите запуск (RUN) вашего скрипта. Udev работает и со сканкодом(scancode) и с кейкодом(keycode) клавиши или сочетания, но только не с символами(keysym) иксов, т.к. иксы на один слой абстракции выше удава. Но в иксах тоже будет отрабатывать, ведь код(keycode) сочетания или клавиши будет проходить сначала через удав, а потом уже идти в иксы, так что скрипт отработает :-) только в скрипт нужно будет добавить какое-нибудь условие на случай если запущены иксы, чтобы через d-bus, например, отправлять notify на рабочий стол, ну, или что у вас там... Удав вообще штука низкоуровневая и с помощью него много чего можно делать, почитайте вики про него или здесь, ещё здесь, и ещё.
[email protected]# cat /dev/ass > /dev/head
А я свои клавиши так и не смог настроить даже через udev. Пытался много раз и пробовал разные методики, но все напрасно.
Главное, в Ubuntu работают все комбинации Fn+FN, в ArchLinux работает только одна комбинация Fn+F1 (suspend). Все клавиши определяются, ошибок в логах нет.
Правда, есть один нюанс, который похоже и портит всю картину - если в evtest выбрать WMI hotkeys, то эти комбинации не определяются. Но разбираться с этим дальше не стал, надоело, а главное у меня WM и можно назначить самому любую комбинацию.

Выкладываю 2 статейки по использованию udev это_1 и это_2, описывают туже процедуру, описанную Sheykhnur.
Пусть все лежит в одном месте, может кому и пригодится.
Ошибки не исчезают с опытом - они просто умнеют
что за некромантия?)
если не ошибаюся у вас hp, а вы отсюда пробовали решение.

з.ы. а если вдруг не заработает один из этих должен помочь /usr/share/X11/xkb/rules/base.lst
Ошибки в тексте-неповторимый стиль автора©
indeviral
что за некромантия?)
Да просто сейчас отписывался в одном топике, в котором дал ссылку на этот топик, а заодно добавил ссылки на пару статеек - лучше когда все в одном месте.
indeviral
если не ошибаюся у вас hp, а вы отсюда пробовали решение.
Пробовал много чего, но больше уже точно не буду - хватит, устал.
c udev бы возможно и сработало бы но не определяются WMI hotkeys, а если вставляешь обычные коды, то эффекта нет. Но возможно причина и не в WMI hotkeys
Ошибки не исчезают с опытом - они просто умнеют
vasek
Но возможно причина и не в WMI hotkeys
да *** его знает )) ссылка
у меня на lenovo v510 тоже не все fn работают...
Ошибки в тексте-неповторимый стиль автора©
 
Зарегистрироваться или войдите чтобы оставить сообщение.