Как написать драйвер для клавиатуры

Обновлено: 13.05.2024

Разработка программного обеспечения для упрощения буквенно-цифрового ввода при невозможности использовать функционал стандартной буквенной клавиатуры. Классификация и установка драйверов. Выбор языка и среды программирования. Пользовательский интерфейс.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 12.03.2013
Размер файла 183,0 K

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

1. Введение

Функциональные возможности стандартной 101/102 кнопочной клавиатуры достаточно широки и удовлетворяют большинству потребностей рядового пользователя. Однако бывают ситуации, когда возможность воспользоваться ими в полном объёме отсутствует. Например, при выходе из строя части букв на дополнительной клавиатуре и невозможности её немедленной замены может возникнуть необходимость завершить набор какой-либо текстовой информации. В такой ситуации необходимо будет воспользоваться экранной клавиатурой, что не очень удобно.

Альтернативной возможностью является использование специализированного программного обеспечения, которое предоставит достаточно удобный, функциональный и привычный способ набора данных, например реализация классического телефонного буквенного ввода на дополнительной клавиатуре.

2. Конструкторский раздел

2.1 Постановка задачи

Основной целью данного проекта является разработка программного обеспечения для упрощения буквенно-цифрового ввода при невозможности использовать весь функционал стандартной буквенной клавиатуры. Программный продукт должен быть совместим с современными ОС семейства Windows (Windows XP, Windows Vista, Windows 7), работающими на архитектуре x86.

2.2 Анализ задачи

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

Приложение-драйвер должно обладать следующими функциями:

1. Обеспечивать ввод букв русского и английского алфавита с дополнительной клавиатуры аналогичный по принципу, применяемому в мобильных телефонах;

2. Так как дополнительная клавиатура является функциональным элементом, предоставляющим возможность быстрого ввода цифровой информации, необходимо обеспечивать режимы работы как стандартный, так и расширенный, с возможностью ввода буквенной информации;

3. Обеспечить корректную работу в любом текстовом редакторе или окне ввода;

4. Быть простым в использовании;

5. Не нарушать и не замедлять работу системы.

В свою очередь, приложение пользовательского режима должно дополнять драйвер следующим функционалом:

1. Обеспечить вывод корректной информации о выбранном символе в дополнительное окно вывода;

2. Предоставить элементы управления, для быстрого переключения режимов ввода (обычный цифровой ввод / расширенный ввод);

2.3 Определение типа разрабатываемого программного обеспечения

В связи с описанными выше требованиями к функциональности, становится очевидным, что реализуемый драйвер должен выполняться в режиме ядра, так как нам необходимо разработать драйвер устройства, напрямую взаимодействующий с подсистемами ядра ОС. Это связано также с тем, что разрабатываемый драйвер, в частности, должен обрабатывать запросы на ввод-вывод посылаемые всеми приложениями, используемыми пользователем. Необходимо так же определить какой тип и класс драйвера будет разрабатываться, о чём будет сказано в дальнейшем.

2.3.1 Классификация драйверов

· Драйверы режима ядра

· Драйверы файловых систем

· Унаследованные

· Драйверы Plug and Play (PnP)

· Видеодрайверы

· Драйверы пользовательского режима

· Драйверы виртуальных устройств

2.3.2 Модель WDM

Windows driver model (WDM) - это спецификация, созданная для упрощения процесса построения драйверов, в данный момент являющаяся стандартной. В соответствие с требованиями корпорации Microsoft все новые драйверы должны разрабатываться, следуя данной спецификации. Это, помимо следования структуре WDM подразумевает также поддержку Plug and Play (PnP) и управления электропитанием.

В модели WDM используется многоуровневый подход, в соответствии с которым каждое устройство управляется минимум двумя драйверами: драйвером шины и функциональным драйвером. Также к устройству могут быть подключены драйверы фильтров.

В категории драйверов WDM выделяют:

Драйверы шин - управляют логическими или физическими шинами. Отвечают за распознавание устройств, подключённых к управляемой ими шине и оповещение о них диспетчера PnP. В контексте WDM шина - это любое устройство, к которому подключены другие физические, логические или виртуальные устройства.

Функциональные драйверы - драйверы, реализующие все операции, необходимые для поддержки работы устройства.

Драйверы классов - драйверы, предназначенные для управления устройствами, относящимися к определенному классу (например, мышь, клавиатура).

Минидрайверы - драйверы, предоставляющие драйверам классов специфическую поддержку для конкретного производителя.

Следует отметить, что зачастую производитель пишет минидрайвер, который реализует специфический функционал, а для дальнейшего обслуживания устройства вызывает драйвер класса. Вместе, драйвер класса и минидрайвер работают как функциональный драйвер для устройства.

Драйверы фильтров - драйверы, перехватывающие операции ввода/вывода для конкретных устройств с целью их расширения или модификации. Их также можно подразделить на:

· Драйверы фильтров шин;

· Низкоуровневые драйверы фильтров (используются для перехвата обращений к портам ввода-вывода);

· Высокоуровневые драйверы фильтров (используются при обработке запросов, идущих от пользователя).

На рисунке 1 представлена схема слоёв модели WDM.

Рис. 1. Уровни абстракций модели WDM

Как известно, большинство операций ввода-вывода, за исключением операций быстрого ввода/вывода, осуществляются с использованием IRP пакетов. Диспетчер ввода-вывода создаёт IRP пакет и передаёт указатель на него драйверу конкретного устройства. Каждый драйвер имеет связанный с ним объект устройства - структуру данных, содержащую указатели на рабочие процедуры драйвера, которые позволяют взаимодействовать драйверу с диспетчером ввода-вывода. Объекты устройств объединены в стек устройства. Внизу стека устройств находится создаваемый драйвером шины объект физического устройства (Physical Device Object - PDO), который создаётся драйвером шины при обнаружении подключения физического устройства. Основным компонентом стека устройств является объект функционального устройства (Functional Device Object - FDO), связанный с функциональным драйвером. Вокруг функционального объекта может быть расположено произвольное количество устройств - фильтров (Filter Device Object - FiDO), создаваемых драйверами фильтров.

На рисунке 2 представлена схема прохождения IRP пакета по стеку устройств.

Рис. 2. Схема стека устройств

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

2.3.3 Модель WDF

В связи с наличием у драйверной модели WDM ряда недостатков ей на смену приходит новая драйверная модель - Windows Driver Foundation (WDF). WDF представляет собой событийно-управляемую, объектно-ориентированную среду для драйверов режима ядра KMDF (Kernel-Mode Driver Framework) и для драйверов пользовательского режима UMDF (User-Mode Driver Framework). Модель WDF значительно упрощает разработку драйверов.

Данная модель построена на понятии инфраструктуры - Framework, на которую возложено:

§ управление жизненным циклом объектов;

§ управление потоком запросов ввода/вывода и уведомлениями питания PnP;

§ определение объектов WDF, которые могут быть инстанцированы WDF-драйверами;

§ предоставление набора DDI - функций, которые могут использоваться WDF - драйверами для управления объектами.

Для предоставления функциональности, специфичной для конкретного устройства Framework вызывает драйвер WDF.

Модель WDF определяет набор объектов, представляющих структурные компоненты драйверов: устройства, память, очереди, запросы ввода/вывода и сам драйвер. Объекты инфраструктуры предоставляют программный интерфейс, который включает в себя:

· Методы - функции, которые могут быть вызваны драйвером для выполнения операций над объектами и изменения их свойств;

· Свойства - доступные драйверу характеристики объекта;

· Функции обратного вызова, необходимые для обработки событий, которые могут быть сгенерированы инфраструктурным объектом.

Драйвер не оперирует самим объектом WDF, вместо этого он получает его дескриптор, с помощью которого он может обращаться к объекту.

Для разработки данного драйвера была выбрана инфраструктура KMDF, так как она представляет программную модель, поддерживающую разработку функциональных драйверов, драйверов-фильтров и драйверов шин. Сама инфраструктура является разделяемой между многими драйверами реентерабельной библиотекой.

программный драйвер интерфейс клавиатура

2.3.4 Структура KMDF-драйвера

Все драйверы KMDF должны иметь следующие компоненты:

· Функция DriverEntry, которая является главной точкой входа в драйвер и создает инфраструктурный объект драйвера.

· Функцию обратного вызова по событию EvtDriverDeviceAdd, которая создает и инициализирует объект устройства, а также вспомогательные объекты, необходимые для работы драйвера.

· Одну или несколько функций обратного вызова EvtXxx, необходимых для обработки событий, возникающих во время работы драйвера.

События PnP обычно реализуются стандартными методами инфраструктуры, поэтому их обработка не входит в состав базовых компонент драйвера. Также драйверам устройств PnP в общем случае не требуется реализовывать функцию выгрузки, так как инфраструктура предоставляет ее по умолчанию.

IN PDRIVER_OBJECT DriverObject, // указатель на объект драйвера WDM

IN PUNICODE_STRING RegistryPath // указатель на путь в реестре

Это первая функция, вызываемая при загрузке драйвера в ОС. Ее вызывает диспетчер ввода/вывода; функция вызывается только один раз. Она должна выполнять следующие действия:

· Создание объекта драйвера (WDFDRIVER), который представляет загруженный в память экземпляр драйвера; создание этого объекта регистрирует драйвер в инфраструктуре.

· выделение требуемых глобально для драйвера ресурсов.

В случае успешного завершения функция возвращает STATUS_SUCCESS, в противном случае - код ошибки.

Функция обратного вызова по событию EvtDriverDeviceAdd

IN WDFDRIVER Driver, // дескриптор объекта драйвера

IN PWDFDEVICE_INIT DeviceInit // указатель на структуру инициализации

Функция отвечает за создание и инициализацию объекта устройства (WDFDEVICE) и связанных с ним ресурсов. Вызывается инфраструктурой при получении уведомления от менеджера PnP об обнаружении нового подключенного устройства, контролируемого драйвером.

Данная функция выполняет следующий набор операций:

· заполнение структуры инициализации информацией, необходимой для создания объекта устройства;

· организация области контекста объекта устройства (создание структуры расширения);

· создание объекта устройства;

· регистрация функций обратного вызова для событий ввода/вывода и создание очередей ввода/вывода для объекта устройства;

· создание интерфейса устройства, если это требуется;

· создание объекта прерываний, если устройство поддерживает прерывания;

· создание объектов WMI.

В случае успешного завершения функция возвращает STATUS_SUCCESS, в противном случае - код ошибки.

Функции обратного вызова для обработки событий

Драйвер KMDF создает эти функции для обработки связанных с объектом событий, например, поступления запроса ввода/вывода или изменения в состоянии энергопотребления, и регистрирует их в инфраструктуре. Инфраструктура предоставляет стандартные обработчики для событий, поэтому драйвер регистрирует только те из них, которые имеют отношение к обслуживаемым им устройствам.

Например, если драйверу необходимо получать от приложения или компонент системы управляющие запросы (IRP с кодом IRP_MJ_CONTROL), он регистрирует функции обратного вызова EvtIoDeviceControl и EvtIoInternalDeviceControl соответственно. Для перехвата, идущего от устройства запроса и его обработки, в драйвере-фильтре предназначена функция обратного вызова KbFilter_Service Callback.

Для решения задачи необходимо определить, какая из функций драйвера будет отвечать за преобразование вводимых с клавиатуры символов.

Функция DriverEntry, отвечающая за загрузку драйвера, вызывается только один раз при загрузке системы, поэтому она для этой цели не подходит. Функция EvtDriverDeviceAdd вызывается только при подключении нового устройства, поэтому она тоже не подходит. Для решения задачи необходимо использовать функцию, использующуюся для обработки запросов ввод-вывода, то есть одну из функций обратного вызова. Так как для преобразования символов необходимо перехватывать и обрабатывать запросы, поступающие от клавиатуры, очевидно, что необходимо воспользоваться функцией KbFilter_Service Callback.

2.4 Алгоритмы работы

Для выполнения поставленной задачи реализуемый драйвер должен выполнять следующие действия:

1. Включение и выключение режима расширения клавиатуры по нажатию заданной клавиши.

Для реализации данной возможности в драйвере написаны функции включения и выключения. Данные функции активируются приложением пользовательского режима посредством IOCTL запросов. Приложение пользовательского режима предоставляет, в свою очередь, удобный интерфейс пользователя для управления работой драйвера.

2. Определение скан кода нажатой клавиши на дополнительной клавиатуре и вывод соответствующего символа алфавита из набора символов, ассоциированного с данной клавишей.

Так как мы реализуем не просто замену одного символа на другой, а сопоставляем одну клавишу группе символов - нам необходимо реализовать механизм выбора требуемой буквы. Для этого производится сравнение текущей нажатой клавиши с предыдущей. Если скан код клавиши не изменился, то мы увеличиваем значение счётчика нажатий на 1, на основании чего впоследствии сможем сопоставить количеству нажатий нужную букву из ассоциированного клавише массива символов. Вывод выбранного символа производится при нажатии клавиши нуль. Ниже приводится таблица, в которой описано используемое в драйвере сопоставление клавиш.

Как в visual studio 15 написать самый простой код на LUA
Хочу написать самый простой код на LUA в VS. Для этого взял готовый пример из книжки, в одну.

Захотел написать самый простой калькулятор
Решил написать самый простой калькулятор, все вроде и работает, но проблемы с делением, можете.

Написать клиент-сервер (самый простой)
Всем доброго времени суток ! Я поставил себе задачу написать клиент-сервер (самый простой) .

Написать самый простой мини-чат
Всем првиет! У меня есть задача: написать самый простой мини-чат! Я даже не понимаю как он.

Мне не нужно возвращать старый системный адрес драйвера клавиатуры, на этом компе я постоянно буду нажимать одну единственную кнопку (любую) и ждать от нее на экране 3 символа 1,0, пробел, и выключать компьютер этот никогда не буду, эта программа с прерыванием на нем будет всегда (но не эта именно, эта не работает как надо, а исправленная)

Добавлено через 21 минуту
Сама по себе задача бессмысленная, оно и понятно, я сам для себя ее создал и пытаюсь сделать, с одной единственной целью - убедиться, что код с аппаратным прерыванием рабочий, а не просто код ради кода.

Добавлено через 3 минуты
В другой теме уважаемы мастера ассемблера давали код для аппаратного прерывания сом порта, с подменой вектора прерывания 0Сh , но его не получилось проверить на практике, и я даже не понял как его проверить? Поэтому и решил поставить себе самую простую задачу на нажатию одной клавиши клавиатуры.

хорошая мысль .
Все кто не дурики знают что делалать с клаваой. Когда мы ещё не родились, люди уже хотели обманывать Сама по себе задача бессмысленная, оно и понятно, я сам для себя ее создал и пытаюсь сделать, с одной единственной целью - убедиться, что код с аппаратным прерыванием рабочий, а не просто код ради кода.
Добавлено через 3 минуты
В другой теме уважаемы мастера ассемблера давали код для аппаратного прерывания сом порта, с подменой вектора прерывания 0Сh , но его не получилось проверить на практике, и я даже не понял как его проверить? Поэтому и решил поставить себе самую простую задачу на нажатию одной клавиши клавиатуры. Вот вам пожалуйста самое аппаратное-преаппаратное прерывание.

Срабатывает, разумеется 2 раза - при нажатии и при отпускании клавиши, как и задумано аппаратным прерывальщиком.
И переходите уже на FASM, а то долго мучиться будете.

Добавлено через 11 минут
Или вот через DOS ещё веселее.

А у вас я смотрю iret отсутствует и в простой программа не входит, поэтому и не работает ничего, да и адрес компилятор сам бы вычислять должен. Я так и не смог нигде найти внятного описания зачем это нужно, тем более без него всё прекрасно работает.

. кто опохмеляется, кто кросс бежит с утра
..кому чего здесь нравится, весёлая Москва

Добавлено через 2 минуты
Kukuxumushu, лучше скажи, как прочитать SMBus

ручками.
Где этот бус вообще находится? Через пси его искать чтоли?
Сейчас явно я не собираюсь этим заниматься, но чисто для интереса хотелось-бы узнать.. R71MT, так эт самое, вот у него и окошечко памяти есть, и порты, и даже IRQ на нём висит. Осталось только мануал на это всё хозяйство найти. Kukuxumushu, а читать её ты в курсе как? Протокол там не подарок. Дай запрос. и жди. Седьмой, твоё нажатие клавиши, не даёт спокойно жить APIC. Перехвати его, чтоб клава вообще ни на что не реагировала. Поставь терминал, и чтоб он тебе выдавал по-каждоому нажатию клавиши по штуке баксов.
Клава самый основной ингредиент компа. IRQ1 о многом говорит

Не понял, что Вы имели в виду, вы мне уже здорово помогли в разных темах по ассемблеру, с моими тупыми вопросами, но вот этот ответ я не понял. Я себя не считаю Д. хотя смотря как на это посмотреть (это вопрос философский и к теме форума не относится), но что делать с Клавой в данном случае не знаю. И зачем Вы к Кукухимусу придираетесь? человек первый откликнулся на вопрос темы, совершил поступок достойный уважения неуча в ассемблере, а Вы его пытаетесь упрекнуть в неверности кода, хотя осталось только проверить рабочий этот код или нет и все станет ясно.

Добавлено через 11 минут

эта команда как я понял, как раз наоборот отключает драйвер и выводит код в дос А для того что бы этот аппаратный драйвер оставался в оперативной памяти, в режиме ожидания нажатия клавиши, эта команда как раз не нужна? А для того что бы этот аппаратный драйвер оставался в оперативной памяти, в режиме ожидания нажатия клавиши, эта команда как раз не нужна? Ваша проблема в том, что вы свои задачи формулируете очень издалека и маленькими кусочками, поэтому вам тут все уже замучились отвечать. Что вы представляете под "драйвером"? Вот у вас DOS работает, и вам какой-то хоткей нужен, по которому всплывает ваша прога, что-то делает, передаёт управление обратно в DOS? Это делает так. А если только ваша программа в монопольном режиме запущена - ничего выдумывать не надо, просто дописывайте код в обработчик, который выше сделали. После перезагрузки нет никаких драйверов. Драйвер - это ты! Возьми управление и всё. Если не даш доське загрузится, то ты хозяит. Кроме аппаратных вещей можешь управлять системой по-своему желанию. я уже не формулирую задачи просто для себя разбираюсь, пытаюсь понять как работает ассемблер, вдруг еще пригодится. тут же студенты наверно в основном обращаются, они на лету схватывают и сдают преподам, а мне просто интересно разобраться как это все работает, может зря вас от дел отвлекаю. ну не отвечайте , мне на этом форуме и так очень много мне помогли, может быть кто нибудь другой ответит, у кого есть время и желание. ничего выдумывать не надо, просто дописывайте код в обработчик,

хорошо так и делаю. спасибо.

Добавлено через 10 минут

перезагрузки чего? Если операционной системы, то понятно что драйверов нет, ну или есть те которые резидентно загружаются вместе с операционной системой. То что моего драйвера нет это понятно. Но мне то нужно что бы запустив драйвер он был постоянно (резидентно), ни какие программы загружаться на комп не будут, просто должен быть компьютер на нем запущен драйвер одной единственной клавиши, которую периодически нажимают и на экране появляется код 1,0, пробел. Кроме аппаратных вещей можешь управлять системой по-своему желанию я не хочу ничем управлять, только одной этой кнопкой. Ну если вам конкретика нужна, то представьте что комп управляет передатчиком высокой мощности и в космос уходит одна единственная фраза "Здравствуйте жители внеземного разума", а кнопку эту нажимает корова, у нее всего одна кнопка и она ее нажимает когда захочет, а программа (драйвер ) должна ожидать нажатие этой кнопки постоянно, и комп никогда не выключается и не перезагружается. Вот так наверно понятнее стала задача?

Если я не ошибаюсь, то работа с клавиатурой - двухуровневая:
1. По аппаратному прерыванию int09h - работа с портами
2. По программному прерыванию int16h.

По аппаратному цепляется русификатор (драйвер) клавиатуры, который обрабатывает коды от нажатия клавиш (они разной длины для разных клавиш) и помещает двубайтный Scan+ASCII коды в выбранной кодировке (например, CP866) в буфер клавиатуры.
По программному - это просто пользовательский интерфейс чтения из буфера клавиатуры.

Вы можете перехватить программное прерывание, и в ответ выдавать свои три символа, вместо одного введённого. Причём реальное чтение из буфера можете осуществлять из своего обработчика, вызывая исходный обработчик.

По аппаратному цепляется русификатор (драйвер) клавиатуры

да мне бы хотелось аппаратное прерывание, оно же быстрее должно срабатывать наверно? А без прицепления русификатора тоже можно (чисто по кнопке) или обязательно с русификатором?

Добавлено через 5 минут

в моем коде нет вот этого простоя, этот код нужен, так получается? Т.е механизм драйвера такой: происходит подмена вектора прерывания и комп зависает (ждет это прерывание)? Но ведь такой метки нет , на которую указывает ссылка безусловного перехода @b?

Что происходит с процессором в этот момент?

Добавлено через 4 минуты
Мне казалось что аппаратный драйвер это некая резидентная программа, которая постоянно находится в оперативной памяти компьютера, и которая при первом запуске подменяет вектор прерывания и код вызываемой программы постоянно находится в оперативной памяти. И по нажатию "нужной" кнопки процессор сразу обращается к этому коду? А так получается что процессор подвисает?

Добавлено через 21 минуту

И переходите уже на FASM, а то долго мучиться будете.

Чем fasm лучше Masm он не правильно компилирует код? С ошибками, вы имеете в виду, и поэтому может не пойти?

Добавлено через 1 час 31 минуту

Добавлено через 5 минут

какое отношение APIS имеет к старому компу архитектуры 80386 на котором я провожу испытание Досовой программы? PS. APIC использовался в многоядерных/многопроцессорных системах, начиная с Intel Pentium (ядро P54). из вики.

Добавлено через 2 минуты

Поставь терминал, и чтоб он тебе выдавал по-каждому нажатию клавиши по штуке баксов.

ну может так и будет, во первых бакс скоро рухнет, а во вторых модуль моей программы тоже будет сколько то стоить может быть как раз бакс, пока не знаю.

Добавлено через 3 минуты

Клава самый основной ингредиент компа. IRQ1 о многом говорит

да именно по этому я и пишу для нее код, пока мысль у вас верная. Но программа все равно не работает, в чем причина, я думаю надо идти в сторону резидентных программ под Досом да? Поскольку она выполняется один раз и Дос пишет, все отлично я свою задачу выполнил, а на самом деле он ошибся, не такая была у него задача.

Добавлено через 4 минуты
еще наверно имеет смысл в отладчике посмотреть адреса векторов аппаратных прерываний и посмотреть какой адрес стоит в смещении 4* 9 =36 , там должен стоять адрес строки 15 кода программы у текущего сегмента, да?

Добавлено через 5 часов 36 минут
Вот нашел совет Завершение программы прерыванием 27H оставляет ее резидентной в памяти. может это мне поможет? Не могу пока найти чем можно посмотреть область памяти MCB до загрузки своей программы и после, что бы убедиться что вектор прерывания изменен и находится в нужном состоянии?

Добавлено через 3 минуты
А в каком месте кода программы надо ставить


DirectX - написать самый простой воксельный движок
Я снова всех приветствую! Возникла необходимость написать самый простой воксельный движок на и.


Самый самый самый простой пример рекурсии
приведите самый прост пример рекурсии)))void main(int k) < int n=10; k=n; k++; n=k; .

Написать самый простой антивирусный сканер, который сможет найти вирус, записанный в автозагрузку
Всем привет, пишу практическую работу по информационной безопасности, необходимо написать самый.

Помогите написать драйвер клавиатуры!
1)Издающий писк только при вводе цифр на дополнительной клавиатуре 2)Издающий писк, если слово.

Давайте обратим наше внимание на драйверы для распространённых устройств ввода, таких как клавиатуры, мыши и сенсорные экраны. Но сначала давайте кратко рассмотрим готовый сервис для доступа к оборудованию, доступный для драйверов ввода.

Serio

Уровень serio предлагает библиотечные подпрограммы для доступа к устаревшему оборудованию ввода, такому как i8042-совместимые контроллеры клавиатуры и последовательный порт. Клавиатуры PS/2 и мыши подключаются к первому, а сенсорные контроллеры с последовательным интерфейсом подключаются к последнему. Для взаимодействия с оборудованием, обслуживаемым serio, например, для передачи команды для PS/2 мыши, предписанные процедуры обратного вызова serio регистрируются с помощью serio_register_driver() .

Чтобы добавить новый драйвер как часть serio, с помощью serio_register_port() регистрируются точки входа open() / close() / start() / stop() / write() . Для примера посмотрите drivers/input/serio/serport.c .

Как можно увидеть на Рисунке 7.1, serio - это только один из маршрутов доступа к низкоуровневому оборудованию. Некоторые драйверы устройств ввода вместо него полагаются на низкоуровневую поддержку от шинных уровней, таких как USB или SPI.

Клавиатуры

Клавиатуры бывают на любой вкус - устаревшие PS/2, USB, Bluetooth, ИК, и так далее. Каждый тип имеет специальный драйвер устройства ввода, но все используют один и тот же драйвер событий клавиатуры, обеспечивая тем самым единый интерфейс для пользователей. Драйвер событий клавиатуры, однако, имеет отличительную особенность по сравнению с другими драйверами событий: он передаёт данные другой подсистеме ядра (уровню tty), а не в пользовательское пространстве с помощью узлов /dev .

Клавиатуры ПК

Клавиатуры ПК (также называемые клавиатурами PS/2 или AT клавиатурами) взаимодействует с процессором через i8042-совместимый контроллер клавиатуры. ПК обычно имеют специальный контроллер клавиатуры, но на ноутбуках взаимодействие с клавиатурой является одной из обязанностей встроенного контроллера общего назначения (смотрите раздел "Встроенные контроллеры" в Главе 20, "Дополнительные устройства и драйверы"). Когда вы нажимаете клавишу на клавиатуре компьютера, это происходит по такому пути:

1. Контроллер клавиатуры (или встроенный контроллер) сканирует и декодирует клавиатурную матрицу и заботится о нюансах, таких как устранение дребезга контактов.

2. Клавиатурный драйвер устройства с помощью serio для каждого нажатия и отпускания клавиши читает с контроллера клавиатуры сырые коды сканирования . Разницей между нажатием и отпусканием является самый старший бит, который для последнего случая установлен. Например, нажатие на кнопку "a" даёт пару скан-кодов, 0x1e и 0x9e . Специальные кнопки экранируются с помощью 0xE0 , так что нажатие кнопки со стрелкой вправо производит последовательность ( 0xE0 0x4D 0xE0 0xCD ). Для наблюдения выходящих из контроллера скан-кодов вы можете использовать утилиту showkey (после символа → идут пояснения):

bash> showkey -s
кл-ра была в режиме UNICODE
[ если вы пробуете это под X, это может не работать, так как
X сервер также читает /dev/console ]

нажмите любую кнопку (программа завершится спустя 10с после
последнего нажатия на кнопку).
.
0x1e 0x9e → Нажатие кнопки "a"

3. Клавиатурный драйвер устройства преобразует полученные скан-коды в коды клавиш, основываясь на режиме ввода. Чтобы увидеть код клавиши, соответствующий кнопке "a":

bash> showkey
.
код кнопки 30 нажатие → Нажатие на кнопку "a"
код кнопки 30 отпускание → Отпускание кнопки "a"

Чтобы сообщить эти коды клавиш дальше вверх, драйвер генерирует событие ввода, которое передаёт управление драйверу событий клавиатуры.

4. Драйвер событий клавиатуры берёт на себя работу по преобразованию кода клавиши в зависимости от загруженной карты кодов клавиш. (Смотрите страницы справки loadkeys и map-файлы в /lib/kbd/keymaps .) Он проверяет, является ли преобразованный код клавиш такими действиями, как переключение виртуальной консоли или перезагрузка системы. Чтобы вместо перезагрузки системы в ответ на нажатие Ctrl+Alt+Del зажглись светодиоды CAPSLOCK и NUMLOCK , добавьте в обработчик Ctrl+Alt+Del драйвера событий клавиатуры, drivers/char/keyboard.c , следующее:

static void fn_boot_it(struct vc_data *vc, struct pt_regs *regs)
<
+ set_vc_kbd_led(kbd, VC_CAPSLOCK);
+ set_vc_kbd_led(kbd, VC_NUMLOCK);
- ctrl_alt_del();
>

5. Для обычных клавиш преобразованный код нажатия отправляется ассоциированному виртуальному терминалу и дисциплине линии N_TTY . (Мы обсуждали виртуальные терминалы и дисциплины линий в Главе 6, "Драйверы последовательных портов.") drivers/char/keyboard.c делает это следующим образом:

/* Добавляем код клавиши в переключаемый буфер */
tty_insert_flip_char(tty, keycode, 0);
/* Планируем */
con_schedule_flip(tty);

Дисциплина линии N_TTY обрабатывает ввод таким образом, что полученные с помощью клавиатуры данные отображаются на виртуальной консоли и позволяет приложениям пользовательского пространства читать символы из узла /dev/ttyX , подключённого к виртуальному терминалу.

На Рисунке 7.3 показано движение данных от момента нажатия клавиши на клавиатуре, до момента его появления на виртуальной консоли. Левая половина рисунка является зависимой от оборудования, а правая половина носит общий характер. В соответствии с целью разработки подсистемы ввода, нижележащий аппаратный интерфейс является прозрачным для драйвера событий клавиатуры и уровня tty. Таким образом, ядро ввода и чётко определённые интерфейсы событий ограждают пользователей ввода от нюансов оборудования.

Рисунок 7.3. Поток данных от PS/2-совместимой клавиатуры.

Рисунок 7.3. Поток данных от PS/2-совместимой клавиатуры.

USB и Bluetooth клавиатуры

Спецификациями USB, связанными с устройствами взаимодействия с человеком (HID), предусмотрен протокол, по которому для взаимодействия используются USB клавиатуры, мыши, наборы кнопок и другие периферийные устройства ввода. На Linux это осуществляется через клиентский драйвер USB usbhid , который отвечает за класс USB HID ( 0x03 ). Usbhid регистрирует себя в качестве драйвера устройства ввода. Он соответствует API ввода и сообщает о соответствующих событиях ввода подключенных HID.

Для того, чтобы понять путь кода для USB клавиатуры, вернёмся к Рисунку 7.3 и изменим аппаратно-зависимую левую половину. Заменим контроллер клавиатуры в квадратике "Оборудование ввода" на контроллер USB, serio на уровень ядра USB и квадратик "Драйвер устройства ввода" на драйвер usbhid.

Для Bluetooth клавиатуры заменим на Рисунке 7.3 контроллер клавиатуры на набор микросхем Bluetooth, serio на уровень ядра Bluetooth и квадратик "Драйвер устройства ввода" на драйвер Bluetooth hidp.

USB и Bluetooth подробно рассматриваются в Главе 11, "Универсальная последовательная шина" и в Главе 16, "Linux без проводов", соответственно.

Мыши, как и клавиатуры, бывают с разными возможностями и имеют различные варианты взаимодействия. Давайте посмотрим на обычно использующиеся.

PS/2 мышь

Мыши генерируют относительные передвижения по осям X и Y. Кроме того, они имеют одну или несколько кнопок. Некоторые из них также имеют колёсико прокрутки. Драйвер устройства ввода для устаревшей PS/2-совместимой мыши для взаимодействия с контроллером основывается на уровне serio. Драйвер событий ввода для мышей, называемый mousedev , сообщает события мыши пользовательским приложениям с помощью /dev/input/mice .

Пример драйвера: Мышь-колёсико

Чтобы получить настоящий драйвер устройства мыши, давайте преобразуем вращающееся колёсико, рассматриваемое в Главе 4, "Создание основы", в вариант обычной PS/2 мыши. "Мышь-колёсико" создаёт одномерное движение по оси Y. Повороты колёсика по часовой стрелке и против часовой стрелки создают положительные и отрицательные относительные Y координаты соответственно (как колесо прокрутки на мыши), а нажатие на колёсико приводит к событию нажатия на левую кнопку мыши. Мышь-колёсико идеально подходит для навигации по меню в таких устройствах, как смартфоны, КПК и музыкальные плееры.

Драйвер устройства мыши-колёсика, реализованный в Распечатке 7.3, работает с оконными системами, такими как X Windows. Чтобы увидеть, как драйвер заявляет о своих похожих на мышь возможностях, посмотрите на roller_mouse_init() . В отличие от драйвера вращающегося колёсика в Распечатке 4.1 Главы 4, драйверу мыши-колёсика не нужны методы read() или poll() , так как о событиях сообщается с использованием API ввода. Обработчик прерывания от колёсика roller_isr() также соответственно изменяется. Убираем служебные действия, выполняемые в обработчике прерывания, использующие очередь ожидания, спин-блокировку и процедуру store_movement() для поддержки read() и poll() .

В Распечатке 7.3, + и - в начале строк обозначают отличия от драйвера вращающего колёсика, реализованного в Распечатке 4.1 Главы 4.

USB клавиатура

Достаточно часто случается, что клавиатура с интерфейсом USB вдруг перестаёт работать в операционных системах семейства Windows. При этом клавиатура работает в других ОС и меню настроек BIOS. Такое часто случается, если подключалась новая клавиатура в другие порты или часто отключались/подключались разные клавиатуры. Так же проблема может возникнуть при подключении неисправной клавиатуры или клавиатуры с поврежденным шнуром, который работает только в определенном положении, то есть имеет плавающий контакт в жиле.

Ситуация выглядит следующим образом: при подключении клавиатуры в USB порт Windows издаёт звук подключения USB устройства, если, конечно, этот звук не отключён, и пытается установить драйвер устройства. После поиска драйверов система сообщает, что драйвер установить не удалось. При этом в системе появляется "Неизвестное устройство" с именем, указанным производителем в контроллере устройства. Для клавиатуры это обычно "HID Keyboard Device". Ни удаление устройства, ни переключение в другие порты, ни перезагрузки, ни пляски с бубном клавиатуру в систему не возвращают. При этом. клавиатура исправно работает В других ОС и в меню настроек BIOS.

Ошибка установки драйвера USB клавиатуры
Неизвестное USB устройство
Неизвестное USB устройство

Такое поведение ОС Windows указывает, что система по какой-то причине не может определить принадлежность устройства к группе клавиатур. При этом ручная установка драйвера с явным указанием типа устройства "USB-устройство ввода" или "HID-совместимое устройство" результата не дают. Windows упорно не желает видеть USB-клавиатуру. Многие псевдоспециалисты, столкнувшись с неполадками драйверов Windows предлагают единственное решение: перестановку системы. И, надо сказать, перестановка решает проблему, даже если систему установили не уничтожая предыдущую. А иногда такие "специалисты" уничтожают систему и все данные пользователя.

Если клавиатура определяется некорректно и выводит странное название устройства нужно сначала удалить драйвер этого устройства и переподключить клавиатуру. Для удаления драйвера неверно определённого устройства: двойной щелчок по иконке вызовет свойства логического устройства, на вкладке Оборудование нажать кнопку Свойства, откроется окно свойств конкретного физического устройства. На вкладке Драйвер нажать кнопку Удалить и подтвердить удаление. Теперь нужно переподключить клавиатуру. Если удаление драйвера не помогло, то решать проблему будем радикально.

Для решения этой проблемы нужно всего лишь "вернуть" Windows сведения об устройстве и его драйвере. Эти сведения находятся в файлах с расширением inf. Windows хранит все inf файлы в нескольких местах. Рабочие, актуальные для системы в данный момент хранятся в папке "c:\Windows\inf\". А все остальные, хоть раз побывавшие в системе, в папке "c:\Windows\System32\DriverStore\FileRepository".

Файл "usb.inf" с настройками USB, в том числе и USB-клавиатур, находиться в папке

c:\Windows\System32\DriverStore\FileRepository\usb.inf_amd64_neutral_269d7150439b3372\ и переподключить устройство. Если до этого для USB-клавиатуры драйвера устанавливались в ручном режиме - их нужно удалить. После переподключения устройства необходимые драйвера будут найдены и установлены.

Если приведённые выше манипуляции не помогли, необходимо проверить, знает ли Windows о клавиатурах вообще. Все настройки этой причудливой системы находятся в реестре. В том числи и об иерархии устройств. Нужные нам параметры находятся в следующих ветвях реестра:

HKEY_LOCAL_MACHINE\SYSEM\CurrentControlSet\Control\Class\<4D36E96B-E325-11CE-BFC1-08002BE10318>
Имя UpperFilters Значение kbdclass HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\<4D36E96F-E325-11CE-BFC1-08002BE10318>
Имя UpperFilters Значение mouclass

Реестр

Если этих параметров нет, то нужно создать мультистроковый параметр UpperFilters и указать значение kbdclass (Правка->Создать->Мультистроковый параметр). Если имя UpperFilters присутствует, но значения нет или оно другое - то двойным щелчком мыши на UpperFilters вызовите редактирование параметра и добавьте слово kbdclass в новой сроке. При этом в других строках параметра могут быть другие значения.

Будьте предельно внимательны при редактировании реестра. Любая ошибка может привести к фатальным последствиям для системы. Не правьте незнакомые параметры, не создавайте лишнего и не удаляйте ничего. Если лезть в реестр страшно - скачайте этот файл и запустите его и разрешите внести данные в реестр. Содержимой файла такое:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\<4D36E96B-E325-11CE-BFC1-08002BE10318>] "UpperFilters"="kbdclass"

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

Иногда причиной неопределения USB клавиатуры могут быть настройки USB портов в BIOS.

USB Keyboard Function
Legacy USB Support

Если BIOS старый, то нужно проверить, включена ли в настройках BIOS опция "USB Keyboard Support - Enabled". В более свежих BIOS версиях должен быть включен пункт "Legacy USB Support - Enabled". Обычно они находятся в меню "Integrated perepherals" или "Advanced". Различные BIOS по разному реагируют на настройку этого параметра. Теоретически, при выключенной опции USB-клавиатура вообще не должна работать никогда. Раньше так, собственно, и было. Однако, сейчас эта функция прекращает обслуживать USB клавиатуру только после завершения процедуры POST. Связано это с прогрессом - портов PS/2, которые раньше традиционно использовались для устройств ввода уже не найти на материнских платах, а BIOS всё больше становится похожим на полноценную ОС благодаря спецификации UEFI. Поэтому поддержка USB клавиатуры при прохождении POST и и загрузке UEFI BIOS полная, а затем, в зависимости от настроек, поддержка отключается. Некоторые старые BIOS позволяют явно указывать где будет осуществляться поддержка USB-клавиатуры - в BIOS или в ОС.

Поддержка USB клавиатуры

В настройках USB портов могут встретиться пункты меню XHCI Hand-off и EHCI Hand-off. Они отвечают за ручное или программное переключения портов в режимы USB 2.0 и USB 3.0. Для ОС Windows эти пункты должны быть отключены: Desable. Эти параметры так же могут повлиять на невозможность обнаружения USB-клавиатуры.

USB XHCI EHCI Hand-off

Так-же некоторые старые BIOS могут экзотично обрабатывать параметр Plug & Play OS (или PNP OS). Для любой современной операционной системы он должен быть YES. Иногда значение этого параметра, установленное в NO может не давать операционной системе обнаружить USB-клавиатуру. Это связано с предоставлением BIOS системе адресов, по которым находиться контроллер портов USB. В современных BIOS, в том числе и в UEFI BIOS такого параметра нет или он не влияет на отображаемое адресное пространство устройств.

Читайте также: