## Общая структура подсистемы ввода ``` ┌───────────────────────────┐ │ │ │ Устройство ввода ◂───────────────────────┐ │ │ │ └─────────────▴─────────────┘ │ │ │ ┌─────────────┴─────────────┐ │ Не HID-совместимое │ │ │ устройство │ HID-драйвер (devh-*) │ │ │ │ │ └─────────────▴─────────────┘ │ │ │ ┌─────────────┴─────────────┐ ┌─────────────┴─────────────┐ │ │ │ │ │ HID-менеджер (io-hid) ◂─── * ───┤ Драйвер ввода (devi-*) ◂───▸ /dev/??? (standalone-режим) │ │ │ │ └───────────────────────────┘ ▲ └─────────────▴─────────────┘ │ │ │ ┌─────────────▾─────────────┐ Интерфейс libhiddi ─────┘ │ │ │ Оконная оболочка Photon │ │ │ └───────────────────────────┘ ``` ## Дерево исходных кодов ``` |- devh/ | |- egalax/ - Исходный код HID-драйвера поддержки тачскринов egalax, подключаемых по USB | |- Makefile - Правила сборки дерева исходников | `- common.mk - Параметры сборки драйверов | `- Makefile - Правила сборки дерева исходников ``` ## Сборка драйвера - Установить и настроить [комплект разработчика](https://help.kpda.ru/help/topic/ru.kpda.doc.dev_tools_ru/html/devkit/devkit.html) для [ЗОСРВ "Нейтрино" редакции 2020](https://help.kpda.ru/help/index.jsp). - Выполнить команду: ``` make ``` ## Запуск драйвера Вместе с менеджером [io-hid](https://help.kpda.ru/help/topic/ru.kpda.doc.os_ru/html/services/io-hid.html): ``` io-hid -d <имя_драйвера|путь к библиотеке> [параметры] ``` С помощью утилиты [mount](https://help.kpda.ru/help/topic/ru.kpda.doc.os_ru/html/utils/utils/mount.html): ``` mount -T io-hid <путь к библиотеке> [параметры] ``` ## Разработка драйвера **Дескриптор драйвера:** ``` struct io_hid_dll_entry { char *name; int nfuncs; int (*init)( void *dll_hdl, dispatch_t *dpp, io_hid_self_t *ioh, char *options ); int (*shutdown)( void *dll_hdl ); } ``` **Дескриптор [io-hid](https://help.kpda.ru/help/topic/ru.kpda.doc.os_ru/html/services/io-hid.html):** ``` struct io_hid_self_t { _Uint32t nfuncs; int (*reg)( void *dll_hdl, io_hid_registrant_t *registrant, int *reg_hdlp ); int (*dereg)( void *dll_hdl ); int (*get_buffer)( int reg_hdlp, void **buffer ); int (*send_report)( int registrant_hdl, void *data, _Uint32t dlen ); } ``` **Инициализация драйвера:** - Заполнить дескриптор устройства (`io_hid_registrant`) - Установить обработчики прерываний и инициализировать ресурсы драйвера - Зарегистрировать драйвер, вызвав функцию `reg()` менеджера [io-hid](https://help.kpda.ru/help/topic/ru.kpda.doc.os_ru/html/services/io-hid.html) (содержится в структуре `io_hid_self_t`) **При получении данных от устройства:** - Заполнить HID-report - Передать HID-report менеджеру [io-hid](https://help.kpda.ru/help/topic/ru.kpda.doc.os_ru/html/services/io-hid.html), вызвав функцию `send_report()` **Дескриптор HID-устройства:** ``` struct io_hid_registrant_t { _Uint32t flags; hidd_device_ident_t *device_ident; /* vid, pid */ void *desc; /* binary descriptor */ _Uint16t dlen; /* binary descriptor length */ _Uint8t reserved[2]; void *user_hdl; io_hid_registrant_funcs_t *funcs; /* callbacks */ _Uint8t reserved2[4]; } ``` **Дескриптор функций драйвера:** Дескриптор функций драйвера определяет структура `io_hid_registrant_funcs`: - Подключение/отключение клиента (`client_attach()` / `client_detach()`) - Управление памятью (`rbuffer_alloc()` / `rbuffer_free()`) - Чтение/Запись HID пакетов (`report_read()` / `report_write()`) - Управление частотой обмена (`get_idle()` / `set_idle()`) - Управление режимом работы (`get_protocol()` / `set_protocol()`) - Получение дополнительных данных от устройства (`string`, `indexed_string`) - Перезагрузка устройства (`reset()`) ## Общий принцип работы HID-драйвера ``` ┌────────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌──────────┐ │ Hardware │ │ devh-* │ │ io-hid │ │ devi-hid │ │ Клиент │ └─────┬──────┘ └─────┬────┘ └─────┬────┘ └──────┬─────┘ └─────┬────┘ │ │ │ │ │ │ │ Регистрация │ │ │ │ ├────────────────────────────▸│ │ │ │ │ │ │ │ │ ├──┐ │ │ │ │ │ │ Регистрация │ │ │ │ │ │ обработчиков прерываний │ │ │ │ │◂─┘ │ │ │ │ Прерывание │ │ │ │ ├──────────────▸│ Отправка HID-report │ │ │ │ │ с помощью send_report() │ Передача │ │ │ ├────────────────────────────▸│ HID-report │ │ │ │ ├─────────────▸│ enqueue_packet() │ │ │ │ ├───────────────────▸│ │ │ │ │ │ ```