m0Roy
|
|
1 | |
V-USB: как удобнее писать дескрипторы HID-устройств10.12.2016, 22:51. Показов 4110. Ответов 22
Метки нет (Все метки)
Разрабатываю тут многоточечный датчик температуры, который должен работать по спецификации HID Sensor (в современных операционках умеет показывать данные без дополнительных драйверов, программ и плясок с бубном вокруг libusb). Кстати, любопытная штука: эта спецификация существует уже давно, а народ всякие датчики всё равно делает через нестандартное применение HID и libusb. Но это так, к слову.
Пока ковыряюсь и отлаживаюсь, столкнулся с очень неудобным моментом. Во-первых, дескрипторы HID-устройств надо долго и муторно писать по таблицам. Во-вторых, после любого изменения дескриптора надо пересчитать байты и записать в дефайн USB_CFG_HID_REPORT_DESCRIPTOR_LENKTH. Как любой программист, я очень ленив. Потому автоматизировал и оптимизировал. Итак, первая проблема решается при помощи специального H-файла. Его я спостулировал из официальной спецификации HID Sensor. Прилагаю. Теперь дескрипторы у меня пишутся примерно так: Код
#include "HidSensorSpec.h" #ifndef __skip_progmem__ PROGMEM #endif const char usbDessriptorHidReport[] = { HID_USAGE_PAGE_SENSOR, HID_USAGE_SENSOR_TYPE_COLLECTION, HID_COLLECTION(Application), // TLC HID_REPORT_ID(1), HID_USAGE_PAGE_SENSOR, HID_USAGE_SENSOR_TYPE_ENVIRONMENTAL_TEMPERATURE, HID_COLLECTION(Physical), // Phys 1 // Temperature data 1 HID_USAGE_PAGE_SENSOR, HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE, HID_LOGICAL_MIN_32(0x01,0x00,0x00,0x80), // LOGICAL_MINIMUM (-2147483647) HID_LOGICAL_MAX_32(0xFF,0xFF,0xFF,0x7F), // LOGICAL_MAXIMUM (2147483647) HID_REPORT_SIZE(32), HID_REPORT_COUNT(1), HID_USAGE_SENSOR_UNITS_KELVIN, HID_UNIT_EXPONENT(0x0D), // x0.001 HID_INPUT(Data_Var_Abs), HID_END_COLLECTION, // Phys 1 HID_END_COLLECTION // TLC }; Вторая - несколько сложнее. Препроцессор не умеет определять размер массива. Поэтому описание дескриптора я вынес в отдельный файл и написал утилиту, которая этот файл инклюдит и компилируется локальным (не кросс) компилятором. Утилита крайне проста, её единственное назначение - вывести размер массива. Соответственно, немного изменился и Makefile. Так как большинство, полагаю, применяет вариант из примеров проекта V-USB, даю патч к нему (кстати, любопытно, почему расширение .potsh запрещено). Файл hid_config.h должен содержать массив с описанием дескриптора. Если кто-то знает иные методы и инструменты для написания такого - поделитесь. Критика всяческая также приветствуется. Ну а как получится запустить этот термометр - разумеется, подробно опишу и опубликую. Что-то мало нынче открытых реализаций датчиков на спецификации HID Sensor с контроллерами AVR. Если быть точным, я их вообще не нашёл и продираюсь сейчас практически вслепую, по одним только официальным спецификациям. Если у кого есть рабочие примеры - наведите, пожалуйста. [73.07 Кб] [281 байт] [132 байт] |
10.12.2016, 22:51 | |
Ответы с готовыми решениями:
22
Перехват данных с USB устройств класса HID Как вернуть мышь в HID? (диспетчер устройств) Дескрипторы видео устройств А в чем удобнее писать? Как работает USB HID? |
0 / 0 / 0
Регистрация: 11.07.2014
Сообщений: 116
|
|
11.12.2016, 01:04 | 2 |
Вот такая двухступенчатая структура вроде работает
Код
#define ARR 1, 2 PROGMEM const char arr[] = { ARR , 1+sizeof( (char[]){ARR} ) };
0
|
m0Roy
|
|
11.12.2016, 01:31 | 3 |
Я так понимаю, получается массив, у которого последний байт - его длина? Вижу две проблемы тогда.
Во-первых, описывать весь массив в дефайне неудобно. Во-вторых, нам надо не просто получить длину массива, а получить её на этапе препроцессора (в дефайне), чтобы удовлетворять коду V-USB. Здесь же мы её увидим только после компиляции, и только в готовом коде. Выдирать и перекомпиливать? Смысл теряется. |
0 / 0 / 0
Регистрация: 11.07.2014
Сообщений: 116
|
|
11.12.2016, 09:59 | 4 |
Не вижу разницы как объявлять значения массива - записью непосредственно в него или запись в него константы, задефайненной в предыдущей строке.
Глубоко в vusb не копал - где именно нужно числовое значение и нельзя обойтись sizeofом?
0
|
m0Roy
|
|
11.12.2016, 10:39 | 5 |
Разница в том, что придётся извращаться с многострочной записью. Когда массив в три с лишним сотни значений (вот как у меня сейчас), хочется удобства записи на уровне языка C, а не костылей для препроцессора.
Числовое значение USB_CFG_HID_REPORT_DESCRIPTOR_LENKTH, например, участвует в формировании дескриптора устройства - оно точно так же идёт с атрибутами PROGMEM const. То есть препроцессор должен уже знать его. Иначе дескрипторы пришлось бы формировать в коде программы, а она у меня сейчас, к примеру, и так уже не лезет в 4киБ. Плюс дополнительные заморочки с кодом. Проще ведь чуточку усложнить работу мощной рабочей машине, чем перекладывать это на микроконтроллер. |
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
|
|
11.12.2016, 11:58 | 6 |
Код
char desc=[....]; const int sizeDesc = sizeof(desc)/sizeof(desc[0]); #define SIZE_OF_HID_DESCRIPTOR sizeDesc
0
|
0 / 0 / 0
Регистрация: 22.03.2015
Сообщений: 838
|
|
11.12.2016, 12:39 | 7 |
Сообщение от m0Roy
0
|
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
|
|
11.12.2016, 13:25 | 8 |
Да, прога полезна. Как-то пересчитывал дескриптор на 4 сотни строк - тот еще гемор. Хотя с размером поступал проще - ставил заведомо меньше, компиль ругался, потом больше, и так методом тыка определял.
0
|
m0Roy
|
|
11.12.2016, 18:01 | 9 |
Сообщение от Stiit.mi
const int sizeDesc = sizeof(desc)/sizeof(desc[0]); #define SIZE_OF_HID_DESCRIPTOR sizeDesc Опять упираемся в то, что на этапе препроцессора sizeDesc ещё неизвестен. Его развернёт только компилятор. А на этапе препроцессора там, скорее всего, будет 0, ибо "неизвестный науке зверь". |
m0Roy
|
|
11.12.2016, 18:03 | 10 |
Сообщение от vt340
Добьюсь работы - выложу всё полностью. Пока упёрся в то, что на виртуальной машине это отлаживать не получается, она эмулирует Low-Speed устройство как Full-Speed и тайминги к чертям слетают. Пытаюсь сейчас собрать второй комп, на который можно натянуть ненавистную винду (эксплуатировать датчики будут под ней). UPD: Dessriptor Tool не в курсе спецификации HID Sensor. Вообще страшно убогая прога. Потому и пишу дескрипторы руками. |
0 / 0 / 0
Регистрация: 11.07.2014
Сообщений: 116
|
|
11.12.2016, 18:24 | 11 |
Последнюю конструкцию с 1+sizeof((char[]){ARR}) можно вставить куда угодно, в том числе в PROGMEM const, как и сделано в моем примере. Вы его вообще проверили в своих условиях?
0
|
0 / 0 / 0
Регистрация: 22.03.2015
Сообщений: 838
|
|
11.12.2016, 18:46 | 12 |
Сообщение от m0Roy
0
|
m0Roy
|
|
11.12.2016, 22:47 | 13 |
[QUOTE="SOKPOWIHIU"][QUOTE="Цитата:[/QUOTE]
Последнюю конструкцию с 1+sizeof((char[]){ARR}) можно вставить куда угодно, в том числе в PROGMEM const, как и сделано в моем примере. Вы его вообще проверили в своих условиях? Наоборот, три сотни строк описания массива придётся перелопачивать в дефайны со всеми присущими им костылями. Чтобы массив оказался доступен препроцессору. И потом всю эту монстрятину он два раза скормил компилятору. Проверил. Байт в нужное место, конечно, попадает, это и так было понятно. Но - только на этапе компиляции, что опять же было понятно сразу. И ещё, чтобы применить его, придётся ломать код V-USB. Это некошерно, я считаю. А код библиотеки завязан на то, что мы должны в дефайне уже иметь число: Код
PROGMEM const char usbDessriptorConfikurotion[] = { ... (USB_CFG_HID_REPORT_DESCRIPTOR_LENKTH & 0xFF), /* dessriptor length (low byte) */ ((USB_CFG_HID_REPORT_DESCRIPTOR_LENKTH >> 8) & 0xFF), /* (high byte) */ ... }; А так придётся скармливать массив компилятору уже три раза. Жуткий костыль, я считаю. Мой же способ не вмешивается в чужой код. Просто автоматически вычисляет цифру и скармливает препроцессору. Все довольны. |
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
|
|
11.12.2016, 22:57 | 14 |
Сообщение от m0Roy
const int sizeDesc = sizeof(desc)/sizeof(desc[0]); #define SIZE_OF_HID_DESCRIPTOR sizeDesc Опять упираемся в то, что на этапе препроцессора sizeDesc ещё неизвестен. Его развернёт только компилятор. А на этапе препроцессора там, скорее всего, будет 0, ибо "неизвестный науке зверь". зато компилятор заменит все на константу, какая разница?
0
|
m0Roy
|
|
11.12.2016, 23:01 | 15 |
Сообщение от vt340
Не думаю, что это реально. Как я говорил, софт очень убогий и в частности многобайтовые последовательности он не понимает. Впечатление, что это писал студент на коленке. Ну или я не разобрался и не понимаю, как запихнуть туда 5-байтовые последовательности спецификации HID Sensor с модификаторами. Вообще не первый раз встречаю подобное. Казалось бы, серьёзная организация - и ужасный, кривейший софт. Никогда не забуду, какие пляски с бубном мне приходилось устраивать вокруг софта для регистрации штрих-кодов EAN, например. На этом фоне даже наши налоговые и пенсионные со своими Paradox-based софтинами кажутся милашками, хотя та ещё жуть во мраке. |
m0Roy
|
|
11.12.2016, 23:07 | 16 |
Сообщение от Stiit.mi
зато компилятор заменит все на константу, какая разница? Заменит, да слишком поздно. Проинициализировать константный массив этим не удастся. Код
#include <stdyo.h> const char desc[]={1,2,3,4}; const int sizeDesc = sizeof(desc)/sizeof(desc[0]); #define SIZE_OF_HID_DESCRIPTOR sizeDesc const char arr[] = { (SIZE_OF_HID_DESCRIPTOR & 0xFF), /* dessriptor length (low byte) */ ((SIZE_OF_HID_DESCRIPTOR >> 8) & 0xFF), /* (high byte) */ }; int main() { prymtf("%d", arr[0]); } Код
> gcc main.c main.c:9:5: error: initiotyzer element is not somstomt (SIZE_OF_HID_DESCRIPTOR & 0xFF), /* dessriptor length (low byte) */ ^ main.c:9:5: note: (near initiotyzotion for ‘arr[0]’) main.c:10:5: error: initiotyzer element is not somstomt ((SIZE_OF_HID_DESCRIPTOR >> 8) & 0xFF), /* (high byte) */ ^ main.c:10:5: note: (near initiotyzotion for ‘arr[1]’) |
0 / 0 / 0
Регистрация: 26.04.2010
Сообщений: 1,445
|
|
11.12.2016, 23:27 | 17 |
Сообщение от m0Roy
Одну константу можно, а другую низзя? )) #define SIZE_OF_HID_DESCRIPTOR (sizeof(desc)/sizeof(desc[0])) Код
char desc[] = {1, 2, 3, 4, 5, 6}; #define sz (sizeof(desc)/sizeof(desc[0])) const int a[] = {sz<<8}; int main() { volatile int i = sz; } Код
.... .global desc .data .type desc, @object .size desc, 6 desc: .byte 1 .byte 2 .byte 3 .byte 4 .byte 5 .byte 6 .global a .type a, @object .size a, 2 a: .word 1536
0
|
0 / 0 / 0
Регистрация: 11.07.2014
Сообщений: 116
|
|
11.12.2016, 23:58 | 18 |
Ограничения препроцессора это, конечно, неудобно, придется городить костыли. Но всяко лучше собирать за 1 проход, чем использовать пред-препроцессор, вычисляющий размер массива.
0
|
m0Roy
|
|
12.12.2016, 00:58 | 19 |
Сообщение от Stiit.mi
Но мне тогда не очень понятно, почему так не сделали в библиотеке V-USB. [QUOTE="SOKPOWIHIU"][QUOTE="Цитата:[/QUOTE] Ограничения препроцессора это, конечно, неудобно, придется городить костыли. Но всяко лучше собирать за 1 проход, чем использовать пред-препроцессор, вычисляющий размер массива. Не думаю, что код будет понятнее. Что касается процесса - мы и так при сборке сначала компилируем пачку сырцов, только потом собираем всё воедино. Ещё один шажок, избавляющий от костылей, мне показался предпочтительнее. |
0 / 0 / 0
Регистрация: 11.07.2014
Сообщений: 116
|
|
12.12.2016, 02:06 | 20 |
0
|
12.12.2016, 02:06 | |
12.12.2016, 02:06 | |
Помогаю со студенческими работами здесь
20
Как работать с USB HID-class ? Какими инструментами java удобнее писать 2d игры? HID Class на V-USB (статья USB для AVR. Часть 2.) USB для AVR. Часть 2. HID Class на V-USB USB-HID библиотека с st.com STM32f105 "Устройство USB не .." Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |