FreeBSD и тачпад
Рассказываю про одную технику решения проблем с тачпадами в этой замечательной ОС. Будет актуально только если вы #банулись настолько чтобы иметь это на ноутбуке.
Проблемы негров
Как вы наверное знаете коль уж читаете эту статью «у холмов есть глаз..» ээм это из другой оперы, «у периферийного оборудования есть драйвера» — специальные программы, реализующие низкоуровневую работу с устройством.
По крайней мере так учит Windows Drivers Kit.
В FreeBSD (так же как и в линуксах) нет концепции «драйвера», вместо нее есть определенная часть ядра, временами даже выгружаемая и отвечающая за работу с устройством или группой устройств одного класса.
Выгружаемая часть чаще всего называется «модулем ядра», но выгрузить можно далеко не все.
Помимо динамической загрузки и выгрузки, существует механизм удаления частей ядра (например отвечающих за ненужное вам оборудование) на стадии сборки — с помощью параметров, указываемых в специальном конфигурационном файле т. н. «конфиге ядра».
В былинные времена, когда сборка из исходников еще не считалась обывателями чем-то зазорным, народ активно обменивался этими самыми конфигами. Верхом мастерства считалось выкидывание максимального количества частей ядра, не имеющих отношения к используемому оборудованию.
К сожалению отключить подобным образом возможно далеко не все, поэтому в который раз придется погрузиться глубже.
Лотерея, лохотрон и выбор устройства
Чтобы ядро ОС могло использовать конкретную часть логики (образно выражаясь — драйвер) для конкретного оборудования, существует сложный многоуровневый механизм определения типа оборудования, который начинается с двух числовых кодов: «device id» и «vendor id».
Vendor ID — код производителя устройства, DeviceID — код устройства.
По идее комбинация этих двух кодов дает уникальное и однозначное определение железки, но конечно же на практике все сильно сложнее:
С появлением производства левой электроники в Китае, весь красивый и логичный механизм централизованного именования, когда за каждым производителем закреплен свой уникальный код Vendor ID — встал и пошел на хер.
Появились дубли, поэтому примерно с начала 2000х полагаться только на DeviceID и VendorID стало фактически невозможно.
Помимо идентификаторов, разные устройства одного типа имеют еще и разные протоколы инициализации - пакеты данных, разного размера и с разными данными внутри.
Что в итоге приводит к необходимости в «логике перебора» — ядро натурально пытается подобрать подходящий драйвер, пуляя в железку разные пакеты инициализации и ожидая на какой она ответит:
Обратите внимание на цикл, выделенный в центре скриншота — вот так выглядит массив с данными, по которому идет итерация:
Видите дублирующиеся коды deviceId (0x08)?
Это означает, что устройства от трех разных производителей считают себя одной семьей отдают один и тот же deviceId.
А от четвертого производителя — нет:
Практически для всех периферийных устройств существуют общепринятые и хорошо поддерживаемые стандартные протоколы взаимодействия, не привязанные к конкретному производителю.
В случае мыши, это например тот самый «Generic Mouse», которым бывает прикидывается тачпад или какая-нибудь особо навороченная модель.
Отсутствие или пробелы в реализации «vendor specific» протоколов плюс неверное определение устройства — создают ту самую «проблему с поддержкой клиентского оборудования», от которой страдают все открытые ОС.
Для решения подобных проблем применяют самый настоящий reverse engineering, восстанавливают по крупицам работу протокола и на свет появляется функционал ядра с поддержкой нового оборудования.
Конечно же это п#здец какой сложный путь, доступный только очень опытным разработчикам. Но есть и другой вариант, сильно проще.
Нормальные герои всегда идут в обход
На одном из моих ноутбуков была давняя проблема с тачпадом — он успешно определялся, но «tap to click» (нажатия по поверхности тачпада) упорно не хотели работать, сколько бы я не крутил настройки.
Проблема была только в BSD, в Linux на этой же машине все работало как надо.
Однажды я обнаружил вот такое сообщение в багтрекере FreeBSD:
удаление кодов (deviceId) устройства из списка поддерживаемых на уровне исходников ядра, для того чтобы ОС использовала стандартный протокол инициализации и работы вместо «vendor specific».
Что я и проделал, внеся правки в файл:
/usr/src/sys/dev/atkbdc/psm.c
Вот так тачпад определялся до патча:
После чего тачпад наконец заработал как надо и я получил работающий «tap to click».
Весь патч заключается в двух закомментированных строчках, отвечающих за инициализацию тачпада конкретной модели:
Разумеется ядро после этого необходимо пересобрать.
P.S.
Описанное в статье вполне актуально и применимо для всех BSD-систем, не только для одной FreeBSD.
Также замечу что подобным образом возможно исправить ситуацию далеко не только с тачпадом — видеокарты, аудио и множество других устройств имеют как свою специфику так и «базовый функционал», который можно попробовать включить аналогичным способом.