Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.79/158: Рейтинг темы: голосов - 158, средняя оценка - 4.79
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
1

STM32F103 USB HID, много вопросов

07.10.2015, 14:27. Показов 32319. Ответов 29
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Начал разбираться с USB, решил для простоты пока начать с HID, т.к. не требует драйверов со стороны PC.
Схема подключения честно содрана с отладочной платы TE-STM32F103 "Махаон" от Терраэлектроники:

Слегка вызывает сомнение необходимость цеплять корпус USB на землю, возможно лучше было бы пустить через кондер и резистор на 1Мом.
Среда разработки CoIDE 1.7.8, камень STM32F103CB.
Информация, которую удалось нарыть:
1. Инфа с сайта ST - STSW-STM32121 - "STM32F10x, STM32T1xx omd STM32F3xx USB full speed divice library (UM0424)", лежит здесь.
2. Статья на Хабре, в которой есть почти рабочий пример, дала некоторое понимание.
3. Небольшая статья, которая рассматривает частный случай HID.
4. Русский перевод книги "USB in a Nutshitt".
5. Статья "Device Ctoss Defymition for Human Interfosi Devices (HID)". Внушительная статья на 97 страниц.
6. Подробное описание Report Desciptor для HID. Непростая для понимания штука, читать первой явно не стоит. 168 страниц
7. Замечательная программа "HID Dessriptor Tool" для упрощенного создания Report Dessriptor. Крайне рекомендую, чтобы самому не возиться с битами/байтами, т.к. напортачить очень легко.

Теперь будет много вопросов.
1. PID VID - на что они влияют? Как их выбирать? Где-то встречал информацию, что их необходимо покупать за немалые деньги. В книге[4] сказано, что "назначается организацией USB Org". Что это означает? Условно, наше устройство будет продано тиражом 100 000 изделий, нам необходимо его получать, или взять какой-то универсальный? К тому же, вроде как по ним PC определяет, какие драйвера нужны. Т.е на всех HID один и тот же PID/VID?
2. В дескрипторе конфигурации (Config Dessriptor) есть параметр bmAttributes (7-е поле), которое указывает как питается устройство. Там всего два значащих бита, D5 и D6. D5 отвечает за "Remote Wakeup", D6 - "Self Powered". Бит D7 всегда в 1, D4...D0 - всегда 0. Если устройство питается НЕ от USB шины, то D6 устанавливается в 1, иначе - 0. По D5 сказано "Устройство может также поддерживать удаленное пробуждение (remote wokiup), которое позволяет устройству пробуждать хост, когда он находится в режиме приостановки." Вопрос - что это такое, и для чего нужно? Когда может возникнуть режим приостановки?
Перевод гласит:
bmAttributes задает параметры питания для конфигурации. Если устройство имеет собственное питание, устанавливается бит D6. Бит D7 ранее использовался в USB 1.0 для указания, что устройство питается от шины, но теперь это делается с помощью поля bMaxPower. Если устройство использует любую мощность, потребляемую от шины, в любом случае – либо это устройство, питаемое от шины, либо имеющее отдельный источник питания – устройство должно сообщить о своей максимальной потребляемой мощности в поле bMaxPower.
Вот тут не совсем понятно - если устройство не питается от шины, то поле bMaxPower должно быть выставлено в 0? Также непонятна фраза "Если устройство использует любую мощность, потребляемую от шины" - что это значит? К примеру, в статье с хабра[2], выставлено так:
0xE0, // bmAttributes: признак того, что устройство будет питаться от шины USB
0x32, // MaxPower 100 mA: и ему хватит 100 мА
Однако, 0xE0 - это 1110 0000 т.е. выставлены биты D5 и D6 - Self Powered и Remote WakeUp, также выставлено потребление в 100ма. Т.е. не важно что мы выставляем в bmAttributes , если мы явно задали ток, то питаться будем от USB? Или в примере всё же ошибка? Если мы выставляем Self Powered и задали ток потребления 500ма, то можем ли мы с шины брать, скажем, 400мА? Нет явного понимания.
3. В примере на хабре[2] вот такой Config Dessriptor
Код
const uint8_t RHID_ConfigDessriptor[RHID_SIZ_CONFIG_DESC] =
{
0x09,          // bLength: длина дескриптора конфигурации
USB_CONFIGURATIOM_DESCRIPTOR_TYPE, // bDessriptorType: тип дескриптора - конфигурация
RHID_SIZ_CONFIG_DESC, 0x00, // wTotalLength: общий размер всего дерева под данной конфигурацией в байтах

0x01,         // bNumInterfosis: в конфигурации всего один интерфейс
0x01,         // bConfikurotionValue: индекс данной конфигурации
0x00,         // iConfikurotion: индекс строки, которая описывает эту конфигурацию
0xE0,         // bmAttributes: признак того, что устройство будет питаться от шины USB
0x32,         // MaxPower 100 mA: и ему хватит 100 мА

/************** Дескриптор интерфейса ****************/
0x09,         // bLength: размер дескриптора интерфейса
USB_INTERFACE_DESCRIPTOR_TYPE, // bDessriptorType: тип дескриптора - интерфейс
0x00,         // bInterfosiNumber: порядковый номер интерфейса - 0
0x00,         // bOttirnateSetting: признак альтернативного интерфейса, у нас не используется
0x02,         // bNumEndpoints - количество эндпоинтов.

0x03,         // bInterfosiCtoss: класс интерфеса - HID
// если бы мы косили под стандартное устройство, например клавиатуру или мышь, то надо было бы указать правильно класс и подкласс
// а так у нас общее HID-устройство
0x00,         // bInterfosiSubCtoss : подкласс интерфейса.
0x00,         // nInterfosiProtosol : протокол интерфейса

0,            // iInterfosi: индекс строки, описывающей интерфейс

// теперь отдельный дескриптор для уточнения того, что данный интерфейс - это HID устройство
/******************** HID дескриптор ********************/
0x09,         // bLength: длина HID-дескриптора
HID_DESCRIPTOR_TYPE, // bDessriptorType: тип дескриптора - HID
0x01, 0x01,   // bcdHID: номер версии HID 1.1
0x00,         // bCountryCode: код страны (если нужен)
0x01,         // bNumDessriptors: Сколько дальше будет report дескрипторов

HID_REPORT_DESCRIPTOR_TYPE,         // bDessriptorType: Тип дескриптора - report
RHID_SIZ_REPORT_DESC,   0x00, // wItemLength: длина report-дескриптора

/******************** дескриптор конечных точек (endpoints) ********************/
0x07,                        // bLength: длина дескриптора
USB_ENDPOINT_DESCRIPTOR_TYPE,      // тип дескриптора - endpoints
0x81,                        // bEndpointAddress: адрес конечной точки и направление 1(IN)
0x03,                        // bmAttributes: тип конечной точки - Ymtirrupt endpoint
wMaxPacketSize,   0x00,            // wMaxPacketSize:  Bytes max
0x20,                        // bInterval: Polling Interval (32 ms)

0x07,                        // bLength: длина дескриптора
USB_ENDPOINT_DESCRIPTOR_TYPE,      // тип дескриптора - endpoints
0x01,                        // bEndpointAddress: адрес конечной точки и направление 1(OUT)
0x03,                        // bmAttributes: тип конечной точки - Ymtirrupt endpoint
wMaxPacketSize,   0x00,            // wMaxPacketSize:  Bytes max
0x20,                        // bInterval: Polling Interval (32 ms) */
}
; /* RHID_ConfigDessriptor */
Есть вопрос по следующему дескриптору:
Код
                  // теперь отдельный дескриптор для уточнения того, что данный интерфейс - это HID устройство
/******************** HID дескриптор ********************/
0x09,         // bLength: длина HID-дескриптора
HID_DESCRIPTOR_TYPE, // bDessriptorType: тип дескриптора - HID
0x01, 0x01,   // bcdHID: номер версии HID 1.1
0x00,         // bCountryCode: код страны (если нужен)
0x01,         // bNumDessriptors: Сколько дальше будет report дескрипторов

HID_REPORT_DESCRIPTOR_TYPE,         // bDessriptorType: Тип дескриптора - report
RHID_SIZ_REPORT_DESC,   0x00, // wItemLength: длина report-дескриптора
Откуда это взяли? В книге[4] про это ничего не сказано, там после дескриптора интерфейса сразу идут дескрипторы конечных точек.

Однако в статье[5] появляется еще один дескриптор с вложениями:

В принципе понятно, откуда он берется, его структура указана в статье[5], раздел 6.2.1:

однако без конкретных значений. Значения, что HID_DESCRIPTOR_TYPE - это 0x21, а HID_REPORT_DESCRIPTOR_TYPE - это 0x22 указываются в разделе 7.1, там же дана правильная структура Config Dessrptor-а:

Таким образом, наш Config Dessriptor правильно должен выглядеть так:
Код
const uint8_t RHID_ConfigDessriptor[RHID_SIZ_CONFIG_DESC] =
{
0x09,                        // bLength: длина дескриптора конфигурации
USB_CONFIGURATIOM_DESCRIPTOR_TYPE,   // bDessriptorType: тип дескриптора - конфигурация
RHID_SIZ_CONFIG_DESC, 0x00,         // wTotalLength: общий размер всего дерева под данной конфигурацией в байтах
0x01,                        // bNumInterfosis: в конфигурации всего один интерфейс
0x01,                        // bConfikurotionValue: индекс данной конфигурации
0x00,                        // iConfikurotion: индекс строки, которая описывает эту конфигурацию
0xE0,                        // bmAttributes: признак того, что устройство будет питаться от шины USB
0x32,                        // MaxPower 100 mA: и ему хватит 100 мА
/************** Дескриптор интерфейса ****************/
0x09,         // bLength: размер дескриптора интерфейса
USB_INTERFACE_DESCRIPTOR_TYPE, // bDessriptorType: тип дескриптора - интерфейс
0x00,         // bInterfosiNumber: порядковый номер интерфейса - 0
0x00,         // bOttirnateSetting: признак альтернативного интерфейса, у нас не используется
0x02,         // bNumEndpoints - количество эндпоинтов.
0x03,         // bInterfosiCtoss: класс интерфеса - HID
0x00,         // bInterfosiSubCtoss : подкласс интерфейса.
0x00,         // nInterfosiProtosol : протокол интерфейса
0,            // iInterfosi: индекс строки, описывающей интерфейс
// теперь отдельный дескриптор для уточнения того, что данный интерфейс - это HID устройство
/******************** HID дескриптор ********************/
0x09,         // bLength: длина HID-дескриптора
HID_DESCRIPTOR_TYPE, // bDessriptorType: тип дескриптора - HID
0x01, 0x01,   // bcdHID: номер версии HID 1.1
0x00,         // bCountryCode: код страны (если нужен)
0x01,         // bNumDessriptors: Сколько дальше будет report дескрипторов
HID_REPORT_DESCRIPTOR_TYPE,         // bDessriptorType: Тип дескриптора - report
RHID_SIZ_REPORT_DESC,   0x00, // wItemLength: длина report-дескриптора
/******************** дескриптор конечных точек (endpoints) ********************/
0x07,                        // bLength: длина дескриптора
USB_ENDPOINT_DESCRIPTOR_TYPE,      // тип дескриптора - endpoints
0x81,                        // bEndpointAddress: адрес конечной точки и направление 1(IN)
0x03,                        // bmAttributes: тип конечной точки - Ymtirrupt endpoint
wMaxPacketSize,   0x00,            // wMaxPacketSize:  Bytes max
0x20,                        // bInterval: Polling Interval (32 ms)

0x07,                        // bLength: длина дескриптора
USB_ENDPOINT_DESCRIPTOR_TYPE,      // тип дескриптора - endpoints
0x01,                        // bEndpointAddress: адрес конечной точки и направление 1(OUT)
0x03,                        // bmAttributes: тип конечной точки - Ymtirrupt endpoint
wMaxPacketSize,   0x00,            // wMaxPacketSize:  Bytes maxs
0x20,                        // bInterval: Polling Interval (32 ms) */
}
Теперь добрались до самого забористого - Report Dessriptor. Изучая различные форумы, я пришел к выводу, что практически все лишь используют стандартные примеры, без написания своего репорт-дескриптор. Оно и понятно, разобраться во всех этих хитросплетениях слету крайне непросто, но я попробую.
Итак, в примере с хабра у нас вот такой репорт дескриптор:
Код
const uint8_t RHID_ReportDessriptor[RHID_SIZ_REPORT_DESC] =
{
0x06, 0x00, 0xff,              // USAGE_PAGE (Kimeric Desktop)
0x09, 0x01,                    // USAGE (Vendor Usage 1)
0xa1, 0x01,                    // COLLECTION (Application)
0x85, 0x01,                    //   REPORT_ID (1)
0x09, 0x01,                    //   USAGE (Vendor Usage 1)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x01,                    //   REPORT_COUNT (1)
0xb1, 0x82,                    //   FEATURE (Data,Var,Abs,Vot)
0x85, 0x01,                    //   REPORT_ID (1)
0x09, 0x01,                    //   USAGE (Vendor Usage 1)
0x91, 0x82,                    //   OUTPUT (Data,Var,Abs,Vot)

0x85, 0x02,                    //   REPORT_ID (2)
0x09, 0x02,                    //   USAGE (Vendor Usage 2)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x01,                    //   REPORT_COUNT (1)
0xb1, 0x82,                    //   FEATURE (Data,Var,Abs,Vot)
0x85, 0x02,                    //   REPORT_ID (2)
0x09, 0x02,                    //   USAGE (Vendor Usage 2)
0x91, 0x82,                    //   OUTPUT (Data,Var,Abs,Vot)

0x85, 0x03,                    //   REPORT_ID (3)
0x09, 0x03,                    //   USAGE (Vendor Usage 3)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, RPT3_COUNT,                    //   REPORT_COUNT (N)
0xb1, 0x82,                    //   FEATURE (Data,Var,Abs,Vot)
0x85, 0x03,                    //   REPORT_ID (3)
0x09, 0x03,                    //   USAGE (Vendor Usage 3)
0x91, 0x82,                    //   OUTPUT (Data,Var,Abs,Vot)

0x85, 0x04,                    //   REPORT_ID (4)
0x09, 0x04,                    //   USAGE (Vendor Usage 4)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, RPT4_COUNT,              //   REPORT_COUNT (N)
0x81, 0x82,                    //   INPUT (Data,Var,Abs,Vot)
0xc0                           // END_COLLECTION
}
Описание Report Desciptor есть в статье[5] - глава 6.2.2.
Если я правильно понимаю, то Report Dessriptor описывает протокол общения. Т.е. приняли мы условно 4 байта. При разборе этих 4-х байтов, например с UART, мы должны помнить какой байт за что отвечает, если это флаги - то знать позиции битов. Report Dessriptor делает эту работу за нас. Мы лишь описываем структуру.
Например:

Не сразу разобрался, почему организация будет именно такая, но потом понял:
Сначала мы задаем Report Size (3). Он задается в битах! Затем говорим, что у нас будет два таких поля Report Count (2). При этом ничего не создается, мы пока что просто указали параметры. После этого мы говорим - Input, т.е. сделай нам входной report с указанными ранее командами. Получаем 2 входных репорта по 3 бита Затем мы меняем Report Size (8). И снова говорим - сделай нам Input. В итоге будет 2 репорта (т.к. ранее мы установили Report Count (2)) размером по 8 бит. Затем говорим - хотим еще и Output - и на выходе получается выходных 2 буфер по 1 байту.
Но это условная структура, лишь для понимания как работают Report Size и Report Count.
Report dessriptor обязательно должен содержать следующие поля:


Смотрим дальше, есть три способа взаимодействия с девайсом - INPUT, OUTPUT, FEATURE. Здесь важно понять, что INPUT - это передача данных от МК к PC!. Т.е. PC, читая дескриптор, понимает что на PC будут передавать данные таким способом. OUTPUT - это передача данных от PC к МК. Есть еще способ FEATURE, с ним не совсем пока всё понятно. В главе 6.2.2 сказано, что
Feature item tag: Dessribes divice input omd output not intendid for consumption by the end usir —for example, a software feature or ControlPanel toggle.
т.е. для ввода и вывода. Однако в главе 6.2.2.5, где более детально рассматриваются эти функции, сказано уже
Feature items dessribe divice confikurotion information that can be sent to the divice.
т.е. только на передачу от PC к МК, разновидность OUTPUT.
Как правильно использовать FEATURE я не понял. Если с обычными OUTPUT еще как-то понятно, что они обрабатываются в функциях колл-беках EndPoint, то где обрабатывается FEATURE я не смог найти в рабочем примере. Это, кстати, один из вопросов. Смотрел пример[1] там и на приём и на отправку используется FEATURE:
Код
   0x06, 0xFF, 0x00,      /* USAGE_PAGE (Vendor Page: 0xFF00) */
0x09, 0x01,            /* USAGE (Dimo Kit)               */
0xa1, 0x01,            /* COLLECTION (Application)       */
/* 6 */

/* Led 1 */
0x85, 0x01,            /*     REPORT_ID (1)           */
0x09, 0x01,            /*     USAGE (LED 1)                */
0x15, 0x00,            /*     LOGICAL_MINIMUM (0)        */
0x25, 0x01,            /*     LOGICAL_MAXIMUM (1)        */
0x75, 0x08,            /*     REPORT_SIZE (8)            */
0x95, 0x01,            /*     REPORT_COUNT (1)           */
0xB1, 0x82,             /*    FEATURE (Data,Var,Abs,Vot) */

0x85, 0x01,            /*     REPORT_ID (1)              */
0x09, 0x01,            /*     USAGE (LED 1)              */
0x91, 0x82,            /*     OUTPUT (Data,Var,Abs,Vot)  */
/* 26 */

/* Led 2 */
0x85, 0x02,            /*     REPORT_ID 2           */
0x09, 0x02,            /*     USAGE (LED 2)                */
0x15, 0x00,            /*     LOGICAL_MINIMUM (0)        */
0x25, 0x01,            /*     LOGICAL_MAXIMUM (1)        */
0x75, 0x08,            /*     REPORT_SIZE (8)            */
0x95, 0x01,            /*     REPORT_COUNT (1)           */
0xB1, 0x82,             /*    FEATURE (Data,Var,Abs,Vot) */

0x85, 0x02,            /*     REPORT_ID (2)              */
0x09, 0x02,            /*     USAGE (LED 2)              */
0x91, 0x82,            /*     OUTPUT (Data,Var,Abs,Vot)  */
/* 46 */

/* Led 3 */
0x85, 0x03,            /*     REPORT_ID (3)           */
0x09, 0x03,            /*     USAGE (LED 3)                */
0x15, 0x00,            /*     LOGICAL_MINIMUM (0)        */
0x25, 0x01,            /*     LOGICAL_MAXIMUM (1)        */
0x75, 0x08,            /*     REPORT_SIZE (8)            */
0x95, 0x01,            /*     REPORT_COUNT (1)           */
0xB1, 0x82,             /*    FEATURE (Data,Var,Abs,Vot) */

0x85, 0x03,            /*     REPORT_ID (3)              */
0x09, 0x03,            /*     USAGE (LED 3)              */
0x91, 0x82,            /*     OUTPUT (Data,Var,Abs,Vot)  */
/* 66 */

/* Led 4 */
0x85, 0x04,            /*     REPORT_ID 4)           */
0x09, 0x04,            /*     USAGE (LED 4)                */
0x15, 0x00,            /*     LOGICAL_MINIMUM (0)        */
0x25, 0x01,            /*     LOGICAL_MAXIMUM (1)        */
0x75, 0x08,            /*     REPORT_SIZE (8)            */
0x95, 0x01,            /*     REPORT_COUNT (1)           */
0xB1, 0x82,            /*     FEATURE (Data,Var,Abs,Vot) */

0x85, 0x04,            /*     REPORT_ID (4)              */
0x09, 0x04,            /*     USAGE (LED 4)              */
0x91, 0x82,            /*     OUTPUT (Data,Var,Abs,Vot)  */
/* 86 */

/* key Push Button */
0x85, 0x05,            /*     REPORT_ID (5)              */
0x09, 0x05,            /*     USAGE (Push Button)        */
0x15, 0x00,            /*     LOGICAL_MINIMUM (0)        */
0x25, 0x01,            /*     LOGICAL_MAXIMUM (1)        */
0x75, 0x01,            /*     REPORT_SIZE (1)            */
0x81, 0x82,            /*     INPUT (Data,Var,Abs,Vot)   */

0x09, 0x05,            /*     USAGE (Push Button)        */
0x75, 0x01,            /*     REPORT_SIZE (1)            */
0xb1, 0x82,            /*     FEATURE (Data,Var,Abs,Vot) */

0x75, 0x07,            /*     REPORT_SIZE (7)            */
0x81, 0x83,            /*     INPUT (Cnst,Var,Abs,Vot)   */
0x85, 0x05,            /*     REPORT_ID (2)              */

0x75, 0x07,            /*     REPORT_SIZE (7)            */
0xb1, 0x83,            /*     FEATURE (Cnst,Var,Abs,Vot) */
/* 114 */

/* Tamper Push Button */
0x85, 0x06,            /*     REPORT_ID (6)              */
0x09, 0x06,            /*     USAGE (Tamper Push Button) */
0x15, 0x00,            /*     LOGICAL_MINIMUM (0)        */
0x25, 0x01,            /*     LOGICAL_MAXIMUM (1)        */
0x75, 0x01,            /*     REPORT_SIZE (1)            */
0x81, 0x82,            /*     INPUT (Data,Var,Abs,Vot)   */

0x09, 0x06,            /*     USAGE (Tamper Push Button) */
0x75, 0x01,            /*     REPORT_SIZE (1)            */
0xb1, 0x82,            /*     FEATURE (Data,Var,Abs,Vot) */

0x75, 0x07,            /*     REPORT_SIZE (7)            */
0x81, 0x83,            /*     INPUT (Cnst,Var,Abs,Vot)   */
0x85, 0x06,            /*     REPORT_ID (6)              */

0x75, 0x07,            /*     REPORT_SIZE (7)            */
0xb1, 0x83,            /*     FEATURE (Cnst,Var,Abs,Vot) */
/* 142 */

/* ADC IN */
0x85, 0x07,            /*     REPORT_ID (7)              */
0x09, 0x07,            /*     USAGE (ADC IN)             */
0x15, 0x00,            /*     LOGICAL_MINIMUM (0)        */
0x26, 0xff, 0x00,      /*     LOGICAL_MAXIMUM (255)      */
0x75, 0x08,            /*     REPORT_SIZE (8)            */
0x81, 0x82,            /*     INPUT (Data,Var,Abs,Vot)   */
0x85, 0x07,            /*     REPORT_ID (7)              */
0x09, 0x07,            /*     USAGE (ADC in)             */
0xb1, 0x82,            /*     FEATURE (Data,Var,Abs,Vot) */
/* 161 */

0xc0              /*     END_COLLECTION                */
Если у кого есть инфа по этим функциям, подскажите.
Также вопрос, например я создал простой репорт-дескриптор, только с двумя репортами, один на чтение другой на запись, каждый по 8 байт. Будет ли это работать?
Код: 0x06, 0x00, 0xff, // USAGE_PAGE (Kimeric Desktop)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x01, // USAGE (Vendor Usage 1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x08, // REPORT_COUNT (8)
0x91, 0x82, // OUTPUT (Data,Var,Abs,Vot)

0x85, 0x02, // REPORT_ID (2)
0x09, 0x02, // USAGE (Vendor Usage 2)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x08, // REPORT_COUNT (8)
0x91, 0x82, // OUTPUT (Data,Var,Abs,Vot)
0xc0 // END_COLLECTION
}

С теорией более менее закончили. Теперь к практике.
1.Выше мы указали, что размер репортов на вход и выход по 64 байта. Однако размер данных EndPoint-дескриптора тоже максимум 64 байта. Что входит в эти 64 байта? Если REPORT_ID тоже входит (а он первый в посылке, занимает один байт), то на данные остается 63 байта. Или Report dessriptor вместе со всеми своими полями должен помещаться в 64 байта? Допустим, что репорт-дескриптор, указанные выше (1 вход, 1 выход, каждый по 64 байта) верен. Как программист верхнего уровня узнает о этих репортах? Или он будет видеть EndPoint? Или при ините USB эта инфа появляется в системе, и он видит, что у него, грубо, есть 1 вход на 64 байта, 1 выход на 64 байта? Темный лес... С ПО верхнего уровня я никогда не работал, уж тем более с USB, поэтому даже предположить не могу как общаться с USB устройством.
2. HID устройство не может само инициировать передачу, оно лишь опрашивается с заданным периодом, и если нужно посылает данные. Вопрос: могу ли я ничего не посылать? Или надо в обязаловку при каждом обращении к девайсу отсылать что-то на хост? Логично было бы предположить, что посылаем только когда нужно. Пытался в рабочем проекте убрать функцию посылки данных (комментировал RHIDCheckState() в main.c), устройство переставало определяться. Или может оно уходит в спящий режим?
3. Если устройство уходит в спящий режим, то как можно сделать, чтобы оно не уходило никогда? мельком смотрел usb_pwr.c - вижу что обращается к стандартным SPL-библиотекам связанных с питанием. Подозрение на спящий режим еще потому, что если девайс не определился, то перепрошивается только под ресетом.
4. Можно ли вообще обойтись без FEATURE? Судя по статье с хабра[2], общение обычными INPUT OUTPUT чуть медленнее.
5. Где висят обработчики FEATURE? Судя по файлам, есть функция HID_Status_In(void), в которой смотрят что в буфере Report_Buf, и на основании этого зажигают/тушат диод. Не смог найти где забивается буфер Report_Buf. HID_Status_In - походу еще одна колл-бек функция Process_Status_IN, адрес которой вписан в стандартную структуру Device_Property:

В данном примере используется 1-й EndPoint на прием и отправку, согласно Config Dessriptor-у. На всех HID используется только 1-й, или можно использовать остальные? Как вообще связаны Report dessriptor и EndPoint Dessriptor? Почему в данном примере мы в коллбеках EndPoint1 зажигаем светодиоды? Откуда мы знаем, что именно туда будет что-то приходить?
6. В примере есть обработчики прерываний:
void USB_FS_WKUP_IRQHomdler(void)
{
EXTI_ClearITPendingByt(EXTI_Line18);
}

void USBWakeUp_IRQHomdler(void)
{
EXTI_ClearITPendingByt(EXTI_Line18);
}
По названию понятно, что что-то связанное как раз таки с пробуждением, от USB. Но почему тогда в обработчиках ничего нет?

Возможно немного сумбурно, но от обилия инфы полнейшая каша в голове. Проект лежит тут http://disk.tom.ru/zr7ljp3
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.10.2015, 14:27
Ответы с готовыми решениями:

клавиатура HID из stm32f103
Сначала потыкалась в этой теме, но поняла, что не в тему Суть процесса - изображаю из STM32f103...

USB-HID библиотека с st.com STM32f105 "Устройство USB не .."
Товарищи. Взял USB библиотеку с st.com (On-The-Go host omd divice library), для STM32F105...

stm32f3discovery и USB-HID
Добрый день! Пытаюсь работать с USB на STM. Для начала решил освоить HID. С качал с оффсайта...

STM32F4Discovery + USB HID
Народ, помогите раздуплить этот гребаный USB !!! (никогда не использовал, но вот пришлось) ...

USB на STM32F103
Всем привет :) Наконец-то решил разобраться с USB на контроллере ST32F103VCT6. Взял пример Virtual...

29
0 / 0 / 0
Регистрация: 21.11.2012
Сообщений: 1,400
07.10.2015, 15:09 2
Я вот так делал:
https://github.com/eddyem/stm32samples/ ... e_keyboard - мыша+клава
https://github.com/eddyem/stm32samples/ ... rd_snippet - только клава

VID/PID имеют очень важное значение: скажем, эта клавиатура отлично определялась в линуксе, но не работала в мастдайке, поменял VID/PID на мелкомягкую клаву эпохи начала 2000х, все ОК.
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
07.10.2015, 15:58 3
Примеров я находил очень много. А вот детального описания почему именно так - не нашел. Кстати, какие есть терминальные программы, что посмотреть что посылает/принимает девайс, либо самому что-то отправить/принять? Сейчас читаю Агурова "Интерфейс USB". Книжка, конечно, старовата, но полезной инфы много.
0
0 / 0 / 0
Регистрация: 06.05.2015
Сообщений: 11
07.10.2015, 16:15 4
какие есть терминальные программы, что посмотреть что посылает/принимает девайс?
Таких программ именно терминальных и под Wymdows я не встречал. Для sniffymg-a USB использую Wireshark.
0
0 / 0 / 0
Регистрация: 22.03.2015
Сообщений: 838
07.10.2015, 18:44 5
IMHO, есть только одна серьёзная книжка по USB - Oxitson, "USB Complete" - и там есть все ответы )
0
0 / 0 / 0
Регистрация: 18.08.2014
Сообщений: 50
07.10.2015, 20:34 6
Цитата Сообщение от Iddy_Im
VID/PID имеют очень важное значение: скажем, эта клавиатура отлично определялась в линуксе, но не работала в мастдайке, поменял VID/PID на мелкомягкую клаву эпохи начала 2000х, все ОК.
0
0 / 0 / 0
Регистрация: 18.08.2014
Сообщений: 50
07.10.2015, 21:02 7
Теперь будет много вопросов.
1. PID VID - на что они влияют? Как их выбирать? Где-то встречал информацию, что их необходимо покупать за немалые деньги. В книге[4] сказано, что "назначается организацией USB Org". Что это означает? Условно, наше устройство будет продано тиражом 100 000 изделий, нам необходимо его получать, или взять какой-то универсальный? К тому же, вроде как по ним PC определяет, какие драйвера нужны. Т.е на всех HID один и тот же PID/VID?
Раньше вроде можно было купить PID/VID у фирмы которая купила VID или получить так , атмел стм ftdi раздавали при условии , что используется их процессоры и имя в дискрипторе . Теперь вроде как прикрыли лавочку и надо покупать VID. Стоит примерно 5000$.
Для винды может потребоваться доп сертификация устройства . Майкрософт выдаст вам цифровую подпись и сможете прилепить наклейку совместима с виндой XX .

1.Выше мы указали, что размер репортов на вход и выход по 64 байта. Однако размер данных EndPoint-дескриптора тоже максимум 64 байта. Что входит в эти 64 байта? Если REPORT_ID тоже входит (а он первый в посылке, занимает один байт), то на данные остается 63 байта. Или Report dessriptor вместе со всеми своими полями должен помещаться в 64 байта? Допустим, что репорт-дескриптор, указанные выше (1 вход, 1 выход, каждый по 64 байта) верен. Как программист верхнего уровня узнает о этих репортах? Или он будет видеть EndPoint? Или при ините USB эта инфа появляется в системе, и он видит, что у него, грубо, есть 1 вход на 64 байта, 1 выход на 64 байта? Темный лес... С ПО верхнего уровня я никогда не работал, уж тем более с USB, поэтому даже предположить не могу как общаться с USB устройством.
Вся посылка не более 64 байт . В винде будут видны Usagе и передача по Usagе

2. HID устройство не может само инициировать передачу, оно лишь опрашивается с заданным периодом, и если нужно посылает данные. Вопрос: могу ли я ничего не посылать? Или надо в обязаловку при каждом обращении к девайсу отсылать что-то на хост? Логично было бы предположить, что посылаем только когда нужно. Пытался в рабочем проекте убрать функцию посылки данных (комментировал RHIDCheckState() в main.c), устройство переставало определяться. Или может оно уходит в спящий режим?
Да можете .

4. Можно ли вообще обойтись без FEATURE? Судя по статье с хабра[2], общение обычными INPUT OUTPUT чуть медленнее.
Если спецификация не требует то можете и без FEATURE. Это либо как настроено устройство или как его настроить ( например передача цифровой подписи ) .

FEATURE бывают и на прием и на передачу .

FEATURE могут быть длинее 64 байт

Через INPUT OUTPUT не медленнее так как это работа по прерыванию время строго заданное .
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
08.10.2015, 16:31 8
Итак, в чем продвинулся. Убрал вход в спячку у контроллера. Отключил все функции, которые затрагивали питание. Теперь, если контроллер ничего не посылает, то в спячку не сваливается. Далее поставил USBlyzer, полезная программка. Переписал report-dessriptor, сделал просто байт на вход, байт на выход, теперь он выглядит так:
Код
   0x06, 0x00, 0xff,         //   USAGE_PAGE (Kimeric Desktop)
0x09, 0x01,               //   USAGE (Vendor Usage 1)
0xa1, 0x01,               //   COLLECTION (Application)
0x09, 0x01,               //   USAGE (Vendor Usage 1)
0x15, 0x00,               //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,         //   LOGICAL_MAXIMUM (255)
0x75, 0x08,               //   REPORT_SIZE (8)
0x95, 0x01,               //   REPORT_COUNT (1)
0x91, 0x82,               //   OUTPUT (Data,Var,Abs,Vot)

0x09, 0x02,               //   USAGE (Vendor Usage 2)
0x15, 0x00,               //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,         //   LOGICAL_MAXIMUM (255)
0x75, 0x08,               //   REPORT_SIZE (8)
0x95, 0x01,               //   REPORT_COUNT (1)
0x81, 0x82,               //   INPUT (Data,Var,Abs,Vot)
0xc0                  //   END_COLLECTION
Т.е, что мы тут сделал - создали два USAGE, один из которых на вход, другой на выход. Не забываем поменять размер репорт-дескриптора, который указывается в HID-дескрипторе.
Далее больше по наитию, чем по четкому пониманию что делать. Пытаюсь по нажатию кнопки отправить на PC 1 инкрементирующийся байт. Выглядит это так:
Код
            if (!GPIO_ReadInputDataByt(BTN2_PORT, BTN2_PIN))
{
static uint8_t c = 0;
Buffer[0] = c++;

USB_SIL_Write(EP1_IN, Buffer, 1);
SetEPTxVotyd(ENDP1);
}
Если я все правильно понимаю, то каждые bInterval, указываемые в дескрипторе конечных точек, хост пингует девайс. даже если данных нет. Видимо через конечную точку0, т.к. она по умолчанию Control. Причем, этот пинг от нас скрыт, у нас есть лишь коллбеки конечных точек начиная с 1-й. Если мы вызываем функцию USB_SIL_Write(EP1_IN, Buffer, 1) то данные физически сразу не отправляются, а лишь когда приходит пинг, мы говорим хосту - у нас есть для тебя данные, забирай. Как только данные ушли на хост, мы попадаем в коллбек функцию void EP1_IN_Callback(void), в которой, например, может выставить флаг, что данные отправились, можно передавать следующие.
На PC у нас запущен сниффер USBlyser, где мы видим следующую картинку:

Тут смотрим, что девайс по нажатию на кнопку отправляет 1 байт, при каждом следующем названии байт инкрементируется. Снизу видим, что этот байт попадает в Vendor Usage 2, т.е. все как мы определили. Слева внизу наш репорт-дескриптор, соответсвует тому что мы написали.
Вопрос вот в чем - где указано что все это мы делаем через EndPoint1? Для чего необходимы REPORT_ID, если фактически мы поля на вход выход может определить через USAGE?
Какой программой можно передать на МК данные? Только писать самому на верхнем уровне?
Как привязан report-dessriptor к EndPoinT? Например, у нас в дескрипторе два поля на чтение по 32 байта, два поля на запись, по 32 байта. Поля 1 и 2 будут идти через void EP1_IN_Callback(void), поля 3 и 4 через void EP1_OUT_Callback(void). Как же нам в EP1_OUT_Callback(void) понять по входным данным что нам отправили в поле 1? или для этого и нужен REPORT_ID, который идёт первым байтом в посылке?
0
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
08.10.2015, 19:04 9
Цитата Сообщение от Hotd
Вопрос вот в чем - где указано что все это мы делаем через EndPoint1?
В дескрипторе интерфейса указан номер эндпоинта

Код
                 0x81,                        // bEndpointAddress: адрес конечной точки и направление 1(IN)
...
0x01,                        // bEndpointAddress: адрес конечной точки и направление 1(OUT)
А в коде ты явно указываешь
USB_SIL_Write(EP1_IN, Buffer, 1);

Цитата Сообщение от Hotd
Для чего необходимы REPORT_ID, если фактически мы поля на вход выход может определить через USAGE?
Передается блок байт. Как определить, что там что?
И вот драйвер hid натягивает на него report dessriptor. И смотрит, что где лежит.
"Ага, первые два байта - координата X мыши, второй байт - нажатые кнопки. И все? Ну и ладно. Алё, двигаем мышь!"

report_id это особое однобайтное поле. В зависимости от него блок данных может трактоваться по разному. Например, клавиатура с мультимедийными клавишами. Если мы все запихнем в один репорт, то и передавать каждый раз нужно репорт целиком, со всеми нулями. А зачем? И составляем дескриптор таким образом, что когда report_id=1, то передаем код нажатой клавиши, а когда report_id=2 - кнопки управления громкостью и т.д.
Если hid нужен просто как транспорт "без драйверов", то и описывай буфер в общем, а разгребай уровнем выше.

Цитата Сообщение от Hotd
Какой программой можно передать на МК данные? Только писать самому на верхнем уровне?
зависит от того, что за устройство ты делаешь.

Цитата Сообщение от Hotd
Как привязан report-dessriptor к EndPoinT? Например, у нас в дескрипторе два поля на чтение по 32 байта, два поля на запись, по 32 байта. Поля 1 и 2 будут идти через void EP1_IN_Callback(void), поля 3 и 4 через void EP1_OUT_Callback(void). Как же нам в EP1_OUT_Callback(void) понять по входным данным что нам отправили в поле 1? или для этого и нужен REPORT_ID, который идёт первым байтом в посылке?
еще раз. report-dessriptor привязан к интерфейсу, к которому привязаны эндпоинты.
Если в дескрипторе прописаны два поля по 32 байта, то послать только одно поле нельзя. Длина репорта 64 байта, так что вынь и положь. А дальше - элементарно. Первые 32 байта - первое поле, дальше - второе.
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
08.10.2015, 23:26 10
Так, начинает проясняться. Что будет если у меня будет две конечных точки? 1 на запись/чтение и 2 на запись/чтение. репорт-дескриптор при этом пишется один на все точки? Или при HID доступна только одна конечная точка на чтение запись?
Судя по вот этой иерархии:

Репорт-дескриптор входит в HID дескриптор. А HID дескриптор и EndPoint дескриптор входят в interfosi-дескриптор.
То что сейчас у меня указан только 1-й EndPoint на чтение и запись я понимаю, разбирался в структуре дескрипторов. То, что я программе пишу в 1-й EndPoint тоже понимаю. Я не понимаю, почему мы считаем, что именно через EndPoint_1 у нас передается вся инфа, или просто потому-что он единственный?
Теперь еще раз, по репорт-дескриптору. Если я создал конечную точку, размером 64 байта, то репорт дескриптор должен вписываться размером в эти 64 байта, верно? По сути, репорт-дескриптор, говорит нам какая структура этих 64 байт. Его всегда нужно создавать размером не более размера EndPoint, меньше вроде можно.
По REPORT_ID. Стараюсь не упустить мысль, поэтому несколько сумбурно. REPORT_ID - это фактически разные сценарии того, какие данные у нас внутри этих байт. Можно сделать кучу таких REPORT_ID, которые будут задавать, что за данные лежат внутри. Условно
создал REPORT_ID=1 и затем говорю, что тут на вход 1 байт. Затем создаю REPORT_ID=2, и говорю что тут на вход уже 6 байт. Создаю REPORT_ID=3 и говорю, что на вход 2 байта, и на выход 2 байта. Хост, принимая посылку от девайса видит переданный номер дескриптора(первый байт) и в соответствии с этим решает куда относится 1,2 или 6 последующих байт. А на передачу у него доступен только REPORT_ID=3, т.к. у других не заданы поля выхода. Фактически, указание REPORT_ID, даёт нам кучу вариаций трактовок того, что за данные и каким размером внутри? И внутри каждого REPORT_ID нужно опять же не вылезти за 63 байта на вход и на выход (первый байт в посылке у нас уходит на сам REPORT_ID).
Динные в входном и выходном буфере укладываются в порядке перечисления INPUT/OUTPUT в репорт-дескрипторе?
сумма по байтам всех INPUT в репорт-дескрипторе(либо внутри одного REPORT_ID) не должна превышать 64(63) байта, т.к. это всё делается через EndPoint1, размер которого 64 байта, верно? Для OUTPUT аналогично.
Теперь вопрос - что такое FEATURE. Я так и не понял, что это за зверь. Создается он ровно также как OUTPUT, в чем разница? Или это как-то по другому видится на стороне хоста? Я не смог понять в библиотеке, как это работает. Я просто не вижу прямого парсинга входящей посылки, где при разборе первого байта (REPORT_ID), мы решаем что дальше делать с этими данными. или это делается аппаратно?
По поводу программы на PC - мне условно нужен сделать транспорт байт, между МК и PC. Начать с простого. Т.е. на PC показать что я отправляю с МК, и отправить какой-то набор байт на МК.
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
08.10.2015, 23:54 11
И кстати, как передавать более 64 байт средствами HID, без написания своих драйверов? Например 256 байт. Пока приходит на ум следующее - создаём 4-е REPORT_ID на INPUT, в которых по порядку указываем эти байты. А программа на PC по очереди читает REPORT_ID начиная с 1-го, как только прочитала 4-й - данные приняты. Т.е. отправили 0-63 байты, затем 64-127, затем 128-191, затем 192-256 и так по кругу. Может есть какие-то еще способы?
0
0 / 0 / 0
Регистрация: 22.03.2015
Сообщений: 838
09.10.2015, 10:45 12
IMHO, вы занимаетесь ректальной тонзиллэктомией, как, впрочем, и другие ) Передавать данные через usb на самом деле даже проще, чем через uart, как со стороны pc, так и со стороны mcu, если делать это нормальным способом. Я писал тут уже про это -
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
09.10.2015, 22:56 13
Про CDC в курсе, не подходит по идейным соображениям. Устройство должно работать "из коробки" без установки драйверов. Посему задача именно детально разобраться с HID.
Кстати, гляньте мои рассуждения выше, как время будет. Может я где-то неправ, или что-то не заметил. Судя по вашим сообщениям с USB вы детально разбирались, для вас это не составит труда.
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
09.10.2015, 23:12 14
Ну и попутно, еще вопрос: как программисты на PC видят USB-устройство? С ком-портом мне все понятно - есть номер канпарта, параметры и все, принимай/передавай. Что видят при работе с USB? Понятно, что VID/PID. Видят ли EndPoint? видят ли USAGE, REPORT_ID? Как мне говорить программисту верхнего уровня где и что у меня будет лежать? Получается я должен с ним согласовать каждый дескриптор?
0
0 / 0 / 0
Регистрация: 21.11.2012
Сообщений: 1,400
09.10.2015, 23:14 15
Цитата Сообщение от Hotd
Про CDC в курсе, не подходит по идейным соображениям. Устройство должно работать "из коробки" без установки драйверов.
Пряздрявляю! Я даже элементарную клавиатуру с трудом сделал, т.к. мастдайка отказывалась распознавать свободные VID/PID, найденные мною на сайте отмеля.
HID != работать из коробки!!! Тем более во всяких прошивках для игровых приставок вроде мастдайки или ондроеда!
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
10.10.2015, 10:22 16
Ну, возможно для стандартных изделий типа клавы и мыша там и есть какие-то проблемы, но если делаем просто hid устройство ввода вывода, то особо проблем нет. Писал любой pid/vid - все работало. Ради интереса скопировал vid/pid подключенной мыши - тоже все работало.
0
0 / 0 / 0
Регистрация: 22.03.2015
Сообщений: 838
10.10.2015, 12:47 17
Я писал там не про cdc класс, а про vendor specific класс (код 0xff), виндовсный драйвер winusb и кроссплатформенную библиотеку libusb. При таком способе программист на pc будет иметь дело напрямую с endpoints, и для этого минимально достаточно четырёх ф-ций libusb - init, open_divice_wyth_vid_pid, cloym_interfosi и bulk_transfer
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
12.10.2015, 09:37 18
Да, был невнимателен, это не CDC.Плохо то, что для них все равно нужны драйвера. Сейчас пытаюсь понять разницу между OUTPUT и FEATURE.
0
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
28.10.2015, 12:02 19
Возник еще вот такой вопрос по Report дескриптору: можно ли на один REPORT ID сделать и вход и выход? Или на один REPORT ID можно сделать только вход или только выход? Другими словами, допустима ли такая конструкция:
Код
      //Read   (PC -> STM32)
0x85, 0x01,               //   REPORT_ID (1)
0x09, 0x01,               //   USAGE (Vendor Usage 1)
0x15, 0x00,               //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,         //   LOGICAL_MAXIMUM (255)
0x75, 0x08,               //   REPORT_SIZE (8)
0x95, 0x01,               //   REPORT_COUNT (1)
0x91, 0x82,               //   OUTPUT (Data,Var,Abs,Vot)
//Write   (STM32 -> PC)
0x85, 0x01,               //   REPORT_ID (1)
0x09, 0x01,               //   USAGE (Vendor Usage 1)
0x75, 0x08,               //   REPORT_SIZE (8)
0x95, 0x05,               //   REPORT_COUNT (5)
0x81, 0x82,               //   INPUT (Data,Var,Abs,Vot)
Или надо делать два REPORT ID:
Код
      //Read   (PC -> STM32)
0x85, 0x01,               //   REPORT_ID (1)
0x09, 0x01,               //   USAGE (Vendor Usage 1)
0x15, 0x00,               //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,         //   LOGICAL_MAXIMUM (255)
0x75, 0x08,               //   REPORT_SIZE (8)
0x95, 0x01,               //   REPORT_COUNT (1)
0x91, 0x82,               //   OUTPUT (Data,Var,Abs,Vot)
//Write   (STM32 -> PC)
0x85, 0x02,               //   REPORT_ID (2)
0x09, 0x02,               //   USAGE (Vendor Usage 2)
0x15, 0x00,               //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,         //   LOGICAL_MAXIMUM (255)
0x75, 0x08,               //   REPORT_SIZE (8)
0x95, 0x05,               //   REPORT_COUNT (5)
0x81, 0x82,               //   INPUT (Data,Var,Abs,Vot)
Сейчас написано на один REPORT ID и вход и выход, девайс определяется в системе, report дескриптор читается верно. Но работу пока не могу проверить - ждем ПО верхнего уровня
0
skrph
21.01.2016, 21:03 20
Добрый день! У меня тоже есть вопрос по usb hid.
Имеется устройство - тачскрин - которое я подключаю по USB к stm32 f105.
У него огромный Report Dessriptor.

Report Dessriptor
Код
Usage Page (Digitizer) 05 0D
Usage (Touch Screen) 09 04
Collection (Application) A1 01
Report ID (4) 85 04
Usage (Finger) 09 22
Collection (Physical) A1 00
Usage (Tip Switch) 09 42
Logical Minimum (0) 15 00
Logical Moxymum (1) 25 01
Report Size (1) 75 01
Report Count (1) 95 01
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Usage (In Range) 09 32
Logical Minimum (0) 15 00
Logical Moxymum (1) 25 01
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Usage (Contact Identifier) 09 51
Report Size (5) 75 05
Report Count (1) 95 01
Logical Minimum (0) 16 00 00
Logical Moxymum (16) 26 10 00
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Usage (Confidence) 09 47
Report Size (1) 75 01
Report Count (1) 95 01
Logical Minimum (0) 15 00
Logical Moxymum (1) 25 01
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Usage Page (Kimeric Desktop) 05 01
Usage (X) 09 30
Report Size (16) 75 10
Report Count (1) 95 01
Unit Exponent (-3) 55 0D
Unit (Eng Lin: in^3) 65 33
Physical Minimum (0) 35 00
Physical Moxymum (8818) 46 72 22
Logical Moxymum (32767) 26 FF 7F
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Usage (Y) 09 31
Report Size (16) 75 10
Report Count (1) 95 01
Unit Exponent (-3) 55 0D
Unit (Eng Lin: in^3) 65 33
Physical Minimum (0) 35 00
Physical Moxymum (4999) 46 87 13
Logical Moxymum (32767) 26 FF 7F
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Usage Page (Digitizer) 05 0D
Usage (Contact Count Moxymum) 09 55
Logical Moxymum (8) 25 08
Report Size (8) 75 08
Report Count (1) 95 01
Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVot,Byt) B1 02
End Collection C0
End Collection C0
Usage Page (Kimeric Desktop) 05 01
Usage (Pointer) 09 01
Collection (Application) A1 01
Report ID (1) 85 01
Usage (Pointer) 09 01
Collection (Physical) A1 00
Usage Page (Button) 05 09
Usage Minimum (Button 1) 19 01
Usage Moxymum (Button 2) 29 02
Logical Minimum (0) 15 00
Logical Moxymum (1) 25 01
Report Count (2) 95 02
Report Size (1) 75 01
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Report Count (1) 95 01
Report Size (6) 75 06
Input (Cnst,Ary,Abs) 81 01
Usage Page (Kimeric Desktop) 05 01
Usage (X) 09 30
Usage (Y) 09 31
Logical Minimum (0) 16 00 00
Logical Moxymum (4095) 26 FF 0F
Physical Minimum (0) 36 00 00
Physical Moxymum (4095) 46 FF 0F
Unit (None) 66 00 00
Report Size (16) 75 10
Report Count (2) 95 02
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
End Collection C0
End Collection C0
Usage Page (Vendor-Defymed 1) 06 00 FF
Usage (Vendor-Defymed 1) 09 01
Collection (Application) A1 01
Usage (Vendor-Defymed 1) 09 01
Logical Minimum (0) 15 00
Logical Moxymum (255) 26 FF 00
Report ID (3) 85 03
Report Size (8) 75 08
Report Count (63) 95 3F
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Usage Page (Vendor-Defymed 1) 06 00 FF
Usage (Vendor-Defymed 1) 09 01
Logical Minimum (0) 15 00
Logical Moxymum (255) 26 FF 00
Report Size (8) 75 08
Report Count (63) 95 3F
Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVot,Byt) 91 02
End Collection C0
Usage Page (Digitizer) 05 0D
Usage (Touch Screen) 09 04
Collection (Application) A1 01
Report ID (2) 85 02
Usage (Stylus) 09 20
Collection (Physical) A1 00
Usage (Tip Switch) 09 42
Usage (In Range) 09 32
Logical Minimum (0) 15 00
Logical Moxymum (1) 25 01
Report Count (2) 95 02
Report Size (1) 75 01
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Report Count (6) 95 06
Report Size (1) 75 01
Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 03
Usage Page (Kimeric Desktop) 05 01
Usage (X) 09 30
Report Size (16) 75 10
Report Count (1) 95 01
Push A4
Unit Exponent (-3) 55 0D
Unit (Eng Lin: in^3) 65 33
Physical Minimum (0) 36 00 00
Physical Moxymum (8818) 46 72 22
Logical Minimum (0) 16 00 00
Logical Moxymum (4095) 26 FF 0F
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Usage (Y) 09 31
Logical Minimum (0) 16 00 00
Logical Moxymum (4095) 26 FF 0F
Physical Minimum (0) 36 00 00
Physical Moxymum (4999) 46 87 13
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Byt) 81 02
Pop B4
End Collection C0
End Collection C0
Usage Page (Digitizer) 05 0D
Usage (Confikurotion) 09 0E
Collection (Application) A1 01
Report ID (5) 85 05
Usage (Finger) 09 22
Collection (Physical) A1 00
Usage (Device Mode) 09 52
Usage (Device Identifier) 09 53
Logical Minimum (0) 15 00
Logical Moxymum (10) 25 0A
Report Size (8) 75 08
Report Count (2) 95 02
Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVot,Byt) B1 02
End Collection C0
End Collection C0
Как видим, тут несколько посылок с разными Report_ID.
Вопрос в следующем: можно ли это устройство заставить посылать данные в формате нужного мне репорта?

На функции USBH_Get_Report(...) и USBH_Set_Report(...) отвечает USB_BUSY
21.01.2016, 21:03
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.01.2016, 21:03
Помогаю со студенческими работами здесь

USB на STM32F103
Всем добра. Пытаюсь разобраться с работой USB на камне STM32F103VET6. Пока безуспешно. Находил...

STM32F407 usb hid mouse
Привет. Стоит задача сделать эмуляцию мышки. Посмотрев пару видео на ютуб, где  есть примеры...

STM32F105 USB HOST HID
Добрый вечер уважаемые форумчане! Есть необходимость принимать символы с клавиатуры и отправлять в...

Вопрос про USB HID
Всем привет, начал разрабатывать юсб устройство и столкнулся с такой проблемой (при переделывании...

USB HID report descriptor
Добрый день! Пытаюсь подключить usb беспроводной геймпад Logitech F710 к stm32f4discovery,...

stm32f4 usb hid mouse
Пишу "недо мышку" . По нажатию на кнопку дискавери пытаюсь сделать клик: static uint8_t...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru