Питер в последние дни зимы это сплошной мрак, серость и уныние, которые вместе с меняющейся погодой способны вогнать в тоску даже самых стойких обитателей.
Именно в такой мрачный февральский день, автор все же решил одну из самых долгоиграющих проблем с оборудованием под FreeBSD.
Которая была изящно описана в официальном багтрекере:
[psm] Курсор мыши замирает на несколько секунд в графическом окружении.
Как это часто бывает, за столь простым описанием скрывался лютейший треш, который выпил немало крови в попытках исправления:
баг никогда не повторялся целиком, поведение отличалось между разными версиями FreeBSD и цикл «засыпания/пробуждения» мог полностью вывести тачпад из строя до перезагрузки.
Ушло пять лет на то чтобы найти причину и решить эту проблему — помните об этом, когда вам будут рассказывать про «быструю разработку и искусственный интеллект, который всех спасет».
Проблема возникала на ноутбуке Fujitsu-Siemens Lifebook U554, но должна была проявиться и на других моделях от других производителей — драйвер тачпада поменял поведение примерно после релиза FreeBSD 10.
Судя по собранному материалу, если на ноутбуке с Linux для решения проблемы с неработающем тачпадом требуется параметр ядра i8042.notimeout при запуске‑ в FreeBSD также наверняка будет повторяться описываемый баг.
Несколько примеров багрепортов для линукса на тему зависания тачпада и использования параметра i8042.notimeout:
https://askubuntu.com/questions/322906/touchpad-doesnt-work-on-fujitsu-lifebook-uh552
https://www.reddit.com/r/linux/comments/2a8cyf/anyway_to_fix_touchpad_without_using/
https://forums.linuxmint.com/viewtopic.php?t=375846&p=2193975
https://www.linux.org/threads/touchpad-not-detectable-in-linux.31846/
Так что проблема для Linux-пользователей известная, но примеров решения для других ОС найти не удалось.
Корень зла
Вот этот маленький блок в исходном коде драйвера psm.c создавал все описанные выше «спецэффекты»:

Суть этого участка кода, в том чтобы отбрасывать полученные данные если они были получены с задержкой, превышающей заданный лимит. Что вообщем‑то логично для такого устройства как тачпад.
Но реалии работы железа в виде «особенных» вендоров вносят свои коррективы, смотрим реализацию аналогичного драйвера в ядре Linux, особенно вот этот замечательный комментарий:
When MUXERR condition is signalled the data register can only contain 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately it is not always the case. Some KBCs also report 0xfc when there is nothing connected to the port while others sometimes get confused which port the data came from and signal error leaving the data intact. They do not revert to legacy mode (actually I’ve never seen KBC reverting to legacy mode yet, when we see one we’ll add proper handling). Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the rest assume that the data came from the same serio last byte was transmitted (if transmission happened not too long ago).
Так что же в итоге происходит:
тачпад отправляет специальные данные, специфичные для этой модели и производителя, драйвер для FreeBSD их отбрасывает по таймауту.
Как это часто бывает: все просто хотели «как лучше».
Патч
Исправление заключается в удалении описанного блока, отвечающего за отбрасывание данных по таймауту.
Конечно это «грязный хак» и такое исправление никогда не примут в апстрим, зато после патча тачпад корректно переживает циклы засыпания-пробуждения и до сих пор не было ни одной паники ядра.
Что дает определенные надежды на стабильность.
В виде DIFF:
--- psm.c 2022-02-17 21:22:45.481834000 +0300
+++ psm.c.1 2022-02-17 21:25:30.616384000 +0300
@@ -3011,14 +3011,14 @@
continue;
getmicrouptime(&now);
- if ((pb->inputbytes > 0) &&
+ /*if ((pb->inputbytes > 0) &&
timevalcmp(&now, &sc->inputtimeout, >)) {
VLOG(3, (LOG_DEBUG, "psmintr: delay too long; "
"resetting byte countn"));
pb->inputbytes = 0;
sc->syncerrors = 0;
sc->pkterrors = 0;
- }
+ }*/
sc->inputtimeout.tv_sec = PSM_INPUT_TIMEOUT / 1000000;
sc->inputtimeout.tv_usec = PSM_INPUT_TIMEOUT % 1000000;
timevaladd(&sc->inputtimeout, &now);
Сохраните как psm.patch
и запустите:
cd /usr/src/sys/dev/atkbdc
patch < /path/to/psm.patch
Обновление на 2025 год
Проблема все также актуальна и без данного исправления, тачпад работать не будет и в текущей версии FreeBSD, поэтому автор страдает накладывает этот патч вручную с каждым новым релизом.
Также добавлю, что из‑за выпуска новых релизов FreeBSD (статья писалась еще для 13й версии) — применение патча «в лоб» скорее всего не сработает. Вам будет необходимо вручную найти проблемный блок и закомментировать его, после чего пересобрать ядро.
Абсолютно точно описанная проблема с тачпадом не является специфичной для отдельной марки ноутбука или тачпада, если у вас она проявляется — пожалуйста дайте знать в комментариях.
Постараюсь все же довести информацию до апстрима.
P.S.
Оригинальная статья была написала в феврале 2022 года на английском, много позже мы выложили русскую версию в нашем блоге, переработанную и обновленную версию которой вы прочитали.
Автор: alex0x08