Метод изменения поведения HID-устройств под управлением ОС Linux

Метод изменения поведения HID-устройств под управлением ОС Linux

Рязанова Н.Ю., Сикорский О.С., МГТУ им.Н.Э.Баумана ryaz_nu@mail.ru, olegsik@gmail.com

Аннотация

В статье рассматривается метод изменения поведения HID устройств. Поведение HID устройств описывается дескриптором отчета (Report Descriptor), поступающим от устройства в модуль HID core. Если устройство правильно реализует протокол своего класса, то для него не нужно разрабатывать специальный драйвер и система автоматически определит его назначение и начнет им управлять. При необходимости изменения поведения устройства нужно только заменить дескриптор отчета устройства новым дескриптором, в котором, например, может быть изменен тип устройства, назначение кнопок и стиков и т.п. Замена осуществляется с помощью HID драйвера устройства, реализуемого как загружаемый модуль ядра.

1 Введение

Класс HID - Human Interface Device (устройства интерфейса пользователя) является одним из наиболее часто используемых классов USB. Класс HID состоит в основном из устройств, предназначенных для интерактивного взаимодействия с компьютером. HID-устройства деляться на следующие типы:

а) клавиатуры и указывающие устройства -например, стандартные компьютерные мыши, трекболы и джойстики;

б) элементы управления на передней панели - например, ручки, переключатели, кнопки и ползунки;

в)элементы управления, которые располагаются на таких устройствах, как телефоны, устройствах дистанционного управление видеомагнитофоном, имитационные устройства - например, перчатки данных, дроссели, рулевые колеса;

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

Другими словами, класс HID охватывает всё или почти всё, исключая лишь, например, подсистему отображения и т. п. Устройство класса USB/HID использует соответствующий драйвер класса HID для извлечения и маршрутизации передаваемых данных. Основу HID-подсистемы составляет модуль ядра hid. Основные структуры данных для HID-подсистемы находятся в файле /linux|/hid.h . Код модуля расположен в файлах ОС Linux /drivers/hid/hid-core.c и /drivers/hid/hid-input.c. Модуль HID rare подгружается в систему, если подключено хотя бы одно HID устройство. За взаимодействие с USB-шиной отвечает модуль usbhid. Код модуля находится в файле /drivers/hid/usbhid/hid-core.c, который является USB-драйвером для USB/HID устройств

Взаимодействие между устройством и HID-ядром ( rare ) в основном выполняется с помощью, так называемых, отчетов ( report ) одного из трех типов: Input, Output и Feature. Модуль usbhid делегирует все действия с дескрипторами отчетов модулю hid. HID core отвечает за парсинг отчетов, интерпретацию отчетов и API пользователя.

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

2 Класс HID-устройств

Спецификация класса устройства для HID

1.11 (Device Class Definition for HID 1.11) или

1.12 предназначена для дополнения стеци-фикации USB и предоставления производителям HID-устройств информации, необходимой для сборки USB-совместимых устройств. Она также определяет, как драйвер класса HID должен извлекать данные из USB-устройств. Маршрутизация и извлечение данных осуществляется путем анализа дескрипторов устройства и данных, которые оно

предоставляет. Устройство HID класса взаимодействует с драйвером HID класса, используя либо канал Управления (Control), либо Прерывания (Interrupt) (рис.1).

Упрравление

Устройство класса HID Драйвер класса HID

Ч •s

?

прерывание

Рис.1

Канал управления используется для :

• приема и посылки ответов на запросы о USB управлении и классе данных,

• отправки данных при опросе драйвером HID класса (запрос отчета (report)),

• приема данных от хоста.

Канал прерывания используется для:

• приема асинхонных (незапрашиваемых данных) от устройства,

• передачи данных с низкой задержкой на устройство (выходящий канал прерывания является дополнительным).

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

Дескриптор устройства класса HID определяет, какие другие дескрипторы класса HID присутствуют, например, Отчетный и Физический дескрипторы (Report and Phisical Descriptors) и указывают их размеры (рис.2). Все данные, переданные на или от HID-устройства, должны быть структурированы в виде отчетов (Report). Дескриптор отчета определяет структуру отчета, которая содержит всю информацию, которая USB-хосту необходима для определения формата данных и действий, определяемые как данные, которые должны быть обработаны.

HID descriptor Type Present Size

Report y Report y

n n

Report

Phisical Descriptor set

Рис. 2

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

Дескриптор отчета описывает каждую часть данных, которые устройство генерирует и определяет, что эти данные фактически представляют.

2.1 HID Usage таблицы

В документе HID Usage Tables 1.12 (буквально - Таблицы использования) определяются константы, которые интерпретируются приложениями для определения цели и значения поля данных или элемента (item) в отчете HID (HID report).

Кроме того, Usages используется для определения значения групп связанных элементов данных. Это достигается путем иерархического представления информации об использовании элементов в коллекции. Usage (буквально - Использование). Причем присвоенные коллекции, применяются к элементам коллекции.

Usages определяет цель коллекции и элементов, из которых она состоит. Каждому элементу ввода, вывода, функции в элементе коллекции может быть назначена цель в виде собственного элемента использования (usage item).

В документе HID Usage Tables содержатся расширения для таблиц, определенных в

определении класса USB/HID устройств. После успешного сканирования дескриптора устройства хост может начать отправлять и получать данные в виде отчетов. Все данные, передаваемые между HID-устройством и хостом, должны быть структурированы в соответствии со спецификациями, указанными в дескрипторе отчета (Report Descriptor). Эти отчеты могут передаваться через любой из каналов: «Контроль» (конечная точка 0), «Прерывание», конечные точки сконфигури-рованые как IN или OUT.

2.2 Структура дескриптора отчета

Дескриптор отчета начинается с элемента Usage Page, который описывает общую функцию всех отчетов устройств одного типа. Например, в дескрипторе отчета для USB-клавиатуры или USB-мыши, разработчики используют Usage page «Общий рабочий стол» [USB.org].

Используя терминологию USB, устройство может отправлять или получать транзакцию на каждый USB-кадр (фрейм USB ) (1 миллисекунда). Транзакция может состоять из нескольких пакетов (токенов, данных, хенд-шейк (handshake)), но ограничена размером до 8 байтов для низкоскоростных устройств и 64 байта для высокоскоростных устройств. Передача - это

2

Рис.3

одна или несколько транзакций, создающих набор данных, которые имеют значение для устройства - например, отчеты «Ввод, Вывод и Функция» (Input, Output и Feature). В этом документе передача является синонимом отчета.

Большинство устройств генерируют отчеты или передачи, возвращая структуру, в которой последовательно представлено каждое поле данных. Однако некоторые устройства могут иметь несколько структур отчетов на одной конечной точке, каждая из которых представляет только несколько полей данных. Например, клавиатура со встроенной мышью может независимо сообщать данные о нажатии клавиш и «указывать» данные курсором на одну и ту же конечную точку. Элементы

Report ID используются для указания полей данных в каждой структуре отчета. Тег элемента идентификатора отчета назначает однобайтовый идентификатор - префикс для каждой передачи отчета. Если в дескрипторе отчета нет тегов элементов идентификатора отчета, можно предположить, что существует только одна структура отчета Input, Output и Feature, и вместе они представляют все данные устройства.

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

Устройства HID используют следующие стандартные USB дескрипторы:

• Устройства

• Конфигурации

• Интерфейса

• Конечной точки

• Строки

Каждый класс устройства содержит один или более классовых дескриптора. Эти дескрипторы отличаются от стандартных USB дескрипторов. Устройства HID класса используют следующие классовые дескрипторы:

1 0

• HID

• Report

• Physical

отличается от других дескрипторов тем, что это не просто таблица значений. Длина и содержание Отчетного Дескриптора зависит от количества полей данных, содержащих информацию об устройстве. Отчетный дескриптор состоит из так называемых элементов, причем первый байт элемента содержит три поля - тип элемента, тег элемента и размер элемента (рис.3). Короткий формат содержит 1 - 5 байт, длинный формат содержит 3 - 258 байт и используется для элементов, требующих большого количества данных. Вместе

23 22 21 20 19 18 17 16 15 14 13 12 10 11 9 8 7 6 5 4 3 2 1 0

[ data ] [ data ] btag btype bsize

эти три поля определяют какую информацию предоставляет элемент:

Имеется три типа элемента - Main, Global и Local и существует пять методов Main:

• Input - тег определяет данные от одного или нескольких элементов управления, размещенных на устройстве. Например, данные, такие как положение одной оси, одной или нескольких кнопок и т.п..

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

• Feature - тег описывает ввод и вывод устройства, который не предназначен для получения конечным пользователем, а предназначен, например, для функции ПО или панели управления переключением.

• Collection - тег определяет смысловое объединение Input, Output и Feature элемента, таких как, мышь, клавиатура, джойстик и указатель.

• End Collection - тег указывает конец набора элементов.

Элементы Input, Output и Feature могут содержать дополнительную информацию - возвращаемые абсолютные или относительные данные. Глобальные или локальные элементы определяют допустимые минимальные и максимальные значения данных. Глобальный элемент определяется на всю структуру.

Для того, чтобы описать данные, передаваемые в Отчётном Дескрипторы (Report Descriptor) должны быть определены следующие элементы:

• Input

• Usage

• Usage Page

• Logical Minimum

• Logical Maximum

• Report Size

• Report Count.

Например, образец элементов, определяющих трех-кнопочную мышь: Usage Page (Generic Desktop),

; Используйте общую Usage Page Usage (Mouse),

Collection (Application),; Открыть набор мышь Usage (Pointer), Collection (Physical),

; Открыть указательный набор Usage Page (Buttons), Usage Minimum (Button 1), Usage Maximum (Button 3),

Logical Minimum (0), Logical Maximum (1),

; поля возвращают данные от 0 до 1 Report Count (3), Report Size (1), ;создать три однобитных поля(кнопки 1,2,&3) Input (Data, Variable, Absolute),

; Создать поле для входных отчетов Report Count (1), Report Size (5),

; Создать пять битное поле констант Input (Constant),

;Добавить поле во входной отчет Usage Page (Generic Desktop), Usage (X), Usage (Y),

Logical Minimum (-127),

Logical Maximum (127),

; поле возвращает значение от -127 до 127

Report Size (8),

Report Count (2),

; Создать два 8 битных поля ( X & Y) Input (Data, Variable, Relative),

; Добавить поля во входящий отчет End Collection,

; Закрыть набор указателя

End Collection

; Закрыть набор мыши

Usage-тег указывает предлагаемый поставщиком устройства способ использования определенного элемента управления или группы элементов управления. Хотя Отчетные Дескрипторы описывают формат данных, например, три 8-битных поля, Usage тег определяет, что должно быть сделано с данными, например, ввод x, y, z.

Рассмотрим отчетный дескриптор стандартной мыши: три кнопки и движение по осям X и Y.

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

Таблица 1. Дескриптор отчета мыши c тремя кнопками

0x05, 0x01, //USAGE_PAGE

0x09, 0x02, // USAGE

0x09, 0x01, // USAGE

0x2 9, 0x03, // USAGE_MAXIMUM

0x15, 0x0 0, // LOGICAL_MINIMUM

0x09, 0x30, // USAGE

0x09, 0x31, // USAGE

0x15, 0x81, //LOGICAL_MINIMUM

0x25, 0x7f, // LOGICAL_MAXIMUM

0x75, 0x08, //REPORT_SIZE

0x95, 0x02, //REPORT_COUNT

0x81, 0x06, //INPUT (Da-

ta,Variable,Relative)

0xc0, // END_COLLECTION

0xc0 // END_COLLECTION

Данный дескриптор описывает отчет, показанный на (рис.4).

Бит! Бшб Бит 5 Бит4 Бит 3 Бит] fini] БитО

Eainü Ьш1 Кнопка L йоюО

Effil ОшсивешшжмиХ

IM ОшгшюешшжвпУ

Рис. 4 Отчет В байте 0 биты 0, 1, 2 предназначены для трех кнопок: кнопка 0 - правая, 1 - средняя и 2 - левая кнопка мыши.

Таким образом, используя только дескриптор отчета, система может определить тип

подключенного устройства и специфику передачи им данных.

3 HID Драйвер

USB-посистема требует, чтобы устройства указывали код производителя и код модели устройства. Эти данные становятся доступными при подключении устройства к компьютеру и находятся в файле ядра dmesg. Например, при подключении к компьютеру мыши с дополнительными клавишами можно увидеть следующую информацию: $ sudo dmesg

[118.44331] usb2-1.3:New USB devise found, idVendor=09da, idProduct=9090

[118.443337] usb2-1.3:Product USB Device [118.443339] usb2-1.3:Manufacturer: A4TECH

Для регистрации HID-драйвера необходимо заполнить массив hid_devise_id (библиотека <linux/mod_devicetable.h>):

#define VENDOR_A4TECH 0x9090 #define PRODUCT_A$TECH 0x09a

static const struct hid_devise_id a4_devices[] = {

{HID_USB_DEVICE ( VENDOR_A4TECH,

PRODUCT_A4TECH ),}, {}

};

Другим примером может служить информация об игровом манипуляторе Du-alShock3/Sixaxis:

#define VENDOR_SONY 0x054c #define PRODUCT_DS3 0x0268

static const struct hid_devise_id ds3_devices[] = {

{HID_USB_DEVICE(VEDOR_SONY,

PRODUCT_DS3 ),}, {}

};

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

Новый дескриптор отчета заменяет старый путем вызова функции report_fixup(), которой передается массив, определяющий значения полей дескриптора отчета.

Данная функция входит в структуру struct hid driver.

Структура struct hid_driver содержит следующие основные поля:

struct hid_driver {

char *name;

const struct hid_device_id *id_table;

int (*probe)(struct hid_device *dev, const struct hid_device_id *id); void (*remove)(struct hid_device *dev); const struct hid_report_id *report_table;

int (*raw_event)(struct hid_device *hdev, struct hid_report *report, u8 *data, int size); int (*event)(struct hid_device *hdev, struct hid_field *field, hid_usage *usage, _s32 value);

void (*report)(struct hid_device *hdev, struct hid_report *report);

_u8 *(*report_fixup)(struct bhid_device *hdev, _u8 *buf, unsigned int *size);

struct device_driver driver;

}

Поле name задает имя драйвера; поле id_table указывает устройства, для которых применяется данный драйвер; функция probe подключает новое устройство; если report является report_table, то вызывается raw_event; если usage является usage_table, то вызывается функция event, функция report_fixup вызывается до того, как выполняется парсинг дескриптора отчета.

Драйвер пишется в виде загружаемого модуля ядра. Точки входа драйвера регистрируются путем инициализации структуры struct hid_driver, например:

struct hid_driver d3_driver= {

.name = "DS3", .id_table = ds3_device, .probe = ds3_probe, .raw_event = ds3_raw_event, .report_fixup = ds3_report_fixup, .remove = ds3_remove,

};

Регистрация и дерегистрация драйвера в системе выполняется в макросах module_init и module_exit с помощью функций hid_register_driver() и hid_unregister_driver(), которым передается адрес инициализированной структуры struct hid_driver:

static int_init ds3_init

{

printk(KERN_INFO "Started ds3 driver.\n"); return hid_register_driver(&ds3_driver);

}

static void_exit ds3_exit

{

hid_unregister_driver(&ds3_driver);

printk(KERN_INFO "Exit.\n"); }

module_init(ds3_init ); module_exit(ds3_exit);

Call-back функция probe() вызывается, когда установлено устройство, которым должен управлять драйвер, поставленный в соответствие устройству модулем HID core. Функция probe() должна выполнять проверку информации, которая передается ей об устройстве, и решать, действительно ли этот драйвер подходит для данного устройства. Функция remove() вызывается ядром при выгрузке драйвера и служит для освобождения ресурсов системы .HID драйвер должен выделять отдельную структуру для каждого устройства при его установке в системе и удалять ее при его отключении. Для рассматриваемого в качестве примера драйвера нужна лишь минимальная структура:

struct ds3_sc {

struct hid_device *hdev;

};

Следующая функция probe() создает структуру struct ds3_sc, связывает ее со структурой struct hid_device и сигнализирует устройству о необходимости начать работу:

static int ds3_probe(struct hid_device *hdev,

const struct hid_device_id *id) {

int ret;

struct ds3_sc *sc;sc=devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);

if(sc==NULL) {

hid_err(hdev,"can't alloc descriptor\n"); return -ENOMEM;

}

hid_set_drvdata

{ hid_err(hdev, "parse faild\n");

returt ret; }

ret = hid_hw_start(hdev,

HID_CONNECT_DEFAULT);

if(ret) {

hid_err(hdev, "hw start failed\n"); return ret;

}

printk(KERN_WARNING "Connect driv-

er\n");

return 0; }

Функция ds3_probe() выделяет память при помощи функции devm_kzalloc(). Функция hid_parse() посылает запрос отчетного дескриптора, а функция hid_hw_start() инициализирует получение отчетов от устройства.

static void ds3_remove(struct hid_device *hdev) {

hid_hw_stop(hdev);

}

Для отключения устройства вызывается функция hid_hw_stop().

Замена отчетного дескриптора происходит в функции ds3_report_fixup(), которой передается три параметра: указатель на структуру устройства hdev, указатель на отчетный дескриптор rdsesc, указатель на длину отчетного дескриптора rsize:

static u8 *ds3_report_fixup

{

hid_info(hdev, "fix ds3 report descriptor\n"); printk(KERN_INFO "fix ds3 report\n"); *rsize = sizeof(sixaxis_rdesc); return sixaxis_rdesc;

}

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

У Dualshock 3 есть одна особенность: несмотря на вызов функций hid_parse и hid_hw_stop, устройство не начнёт посылку отчётов, если не запросить отчёт под номером 0xF2 вручную.

Для запроса отчета драйвере используется функция ds3_set_operational_usb: #define SIXAXIS_REPORT_OxF2_SIZE 17 static int ds3_set_operational_usb(struct

hid_device *hdev) {

u8 *buf; int ret;

buf = kmal-

loc(SIXAXIS_REPORT_0xF2_SIZE,

GFP_KERNEL);

if

return -ENOMEM;

ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_OxF2_SIZE, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) {

hid_err(hdev, "can't set operational

mode"); }

kfree(buf); return ret;

}

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

static int ds3_raw_event

{

int x, y, wheel; x = rd[6] - 127; y = rd[7] - 127; wheel = rd[9] - 127;

if (x < 30 && x > -30) {

rd[6] = 0;

}

else {

if (x > 0) rd[6] = x - 30; else if (x < 0) rd[6] = x + 30;

}

if (y < 30 && y > -30) {

rd[7] = 0;

}

else {

if (y > 0) rd[7] = y - 30; else if (y < 0) rd[7] = y + 30;

}

if (wheel < 30 && wheel > -30) {

rd[9] = 0;

}

else {

if (wheel > 0) rd[9] = wheel - 30;

else if (wheel < 0) rd[9] = wheel + 30;

}

// делим на 10, поступающие значения rd[6] = ((signed char)rd[6]) / 10; rd[7] = ((signed char)rd[7]) / 10; rd[9] = ((signed char)rd[9]) / -10; return 0;

}

3.1 Изменение дескриптора отчета

Для получения дескриптора отчета конкретного устройства необходимо отключить устройство. Иначе система не позволит посмотреть дескриптор. Зная, что DualShock 3 является шестым USB-устройством в USB-концетраторе 3 надо написать в командной строке:

$sudo bash -c "echo -n 3-6:1.0 >

/sys/bus/usb/drivers/usbhid/unbind" Кроме того, посмотреть дескрипторы устройства можно с помощью команды lsusb: $ lsusb -vd 054c:0268

В более удобном виде дескриптор отчета можно найти в файле hid-sony.c: static u8 sixaxis_rdesc[] = {

0x05, 0x01, /* Usage Page (Desctop) */

0x09, 0x04, /*Usage (Joystick) */

0x85, 0x01, /* Report ID (1) */

0x75, 0x08, /* Report Size (8) */

0x95, 0x01, /* Report Count (1) */

0x81, 0x03, /* Input(Const, Var) */

0x35, 0x00, /* Phisical Minimum (0) */ 0x45, 0x01, /* Phisical Maximum (1)*/

0x19, 0x01, /* Usage Minimum (01h)*/ 0x29, 0x13, /* Usage Maximum (13h)*/

0x09,0x01, /* Usage (Pointer) */ 0xA 1,0x00,/*Collection (Physical) */ 0x75, 0x08, /* Report Size (8) */

0x95, 0x04, /* Report Count (13) */ 0x35, 0x00, /*Physical Minimum (0) */ 0x46, 0xFF, 0x00,/*Physical Max-m(255)*/ 0x09, 0x30, /* Usage (X) */

0x09, 0x31, /* Usage (Y) */

0x09, 0x32, /* Usage (Z) */

0x09, 0x35, /* Usage (Rz) */

0xC0, /* End Collection */

0xC0 /* End Collection */

};

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

Рис. 5 Фрагмент отчета Игрового манипулятора

Проведенный эксперимент позволил сопоставить определенные поля отчета с элементами управления на Игровом манипуляторе (рис.5). В результате для игрового манипулятора DualShock 3 было решено, что кнопка "Квадрат" будет имитировать левую кнопку мыши, кнопка "Круг" - правую кнопку, а кнопка правого стика - среднюю кнопку. Курсор перемещается с помощью левого сти-ка, а колесико - с помощью правого стика. Из-за того, что мышь должна передавать координаты изменения своего положения в относительных координатах, а в отчёте от сти-ков приходят абсолютные координаты, необходимо в приходящем отчёте преобразовать пришедшие координаты, а именно вычесть из них 127, чтобы нейтральное положение сти-ков соответствовало нулю.

Во-первых, заменяем тип устройства. Как видно из таблицы 1 Usage типа «Мышь» (0х02) находится на Usage Page Generic Desktop (0x01). Манипулятор уже использует Generic Desktop (0x01), поэтому надо заменить только вторую строку дескриптора на: 0х09, 0х02, /* Usage (Mouse) */ Следующие строки отчета - Report ID и неиспользуемый байт - не изменяем их.

этого изменяют поля дескриптора отчета.

Бит 7 Б:« 6 Бит 5 Бит 4 Бит 3 Бит 2 Бит 1 БитО

БайтО Report ГО

1 Не используется

Байт 1 DLeft DDout D Right DUp Start R3 L3 Select

БайтЗ Square X Circle Triangle RI LI R2 L2

Байт 6 Ось X левого ежа

Байт 7 ОсьУлевогоспка

Байт 8 Ось X правого аш

Байт? Ось Управого ежа

Далее необходимо пропустить два бита, которые передают информацию о кнопках Select и L3.

Для этого в дескрипторе указывается поле из двух бит ( или два поля по одному биту ), где не указывается Usage:

0x75, 0x01, /* Report Size (1) */ 0x95, 0x02, /* Report Count (2) */ 0x81, 0x02, /* Input (Variable) */ После этого устанавливается бит, отвечающий за среднюю кнопку манипулятора-мыши:

0x75, 0x01, /* Report Size (1) */ 0x95, 0x01, /* Report Count (1) */ 0x15, 0x00, /* Logical Minimum (0)*/ 0x25, 0x01, /* Logical Maximum (1)*/ 0x35, 0x00, /*Physical Minimum (0)*/ 0x45, 0x01, /*Physical Maximum (1)*/ 0x05, 0x09, /* Usage Page (Button) */ 0x19, 0x03, /* Usage Minimum (3) */ 0x29, 0x03, /* Usage Maximum (3) */ 0x81, 0x02, /*Input (Variable) */ Аналогично определяются левая и правая кнопки мыши.

Для описания перемещения курсора мыши надо описать оси X и Y:

0x09, 0x01, /* Usage (Pointer) */ 0xA1, 0x00, /* Collection (Physical) */ 0x75, 0x08, /* Report Size (8) */ 0x95, 0x02, /* Report Count (2) */ 0x35, 0x81, /*Physical Minimum (-127)*/ 0x45, 0x7F, /*Physical Maximum (127)*/ 0x09, 0x30, /* Usage (X) */

0x09, 0x31, /* Usage (Y) */

0x81, 0x06, /* Input (Variable,Relative)*/ 0xC0, /* End Collection */ Следует отметить, что в оригинальном дескрипторе стики передавали значение от 0 до 255 в абсолютных координатах. В измененном дескрипторе ввод определяется как относительный (Relative) и значения изменяются в диапазоне от -127 до 127. Аналогично определяется колесо мыши.

Результатом выполненных изменений в Отчетном Дескрипторе Игрового манипулятора является то, что система воспринимает его как «мышь» с тремя кнопками. Изменяя Отчетные Дескрипторы, можно получать новые свойства внешних устройств, подключаемых к вычислительной системе.

Список литературы

Universal Serial Bus. USB.org-HID Tools. 2004 ^^^.шЬ.ащСцата обращения: 23.12.20017) Universal Serial Bus (USB). HID Usage Tables. 10/28/2004. Version 1.12

URL:http://www.usb.org

USB Human Interface Device (HID). 2012. Con-figuration-Linux-USB.org. www.linux-

usb.org >USB-guide

Jonatan Corbet, Alessandro Rubini, 2005 Linux Device Drivers. 3-edition. O'Reilly Media

Универсальная последовательная шина (USB). Описание класса устройств, взаимодействующих с человеком (HID). Спецификация 6/27/01. Версия 1.11.

Васюнин А.Н.,Рязанова Н.Ю.,Тарасенко Е.В. 2016

Анализ методов изменения функциональности внешних устройств в ОС Linux. Автоматизация. Современные технологии. №10, стр.3-8.

Bootlin. Embedded Linux Experts. URL:http://www.elixir.bootlin.com

Linux/hid-sony.c at master torvalds. GitHub. URL:http://www.github.com

The Linux Kernel Archives.

URL:http://www.kernel.org

Анатомия загружаемых модулей ядра Linux -IBM. 13.11.2008.URL:http://www.ibm.com