Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/21: Рейтинг темы: голосов - 21, средняя оценка - 5.00
m0Roy
1

V-USB: как удобнее писать дескрипторы HID-устройств

10.12.2016, 22:51. Показов 4110. Ответов 22
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Разрабатываю тут многоточечный датчик температуры, который должен работать по спецификации 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 байт]
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.12.2016, 22:51
Ответы с готовыми решениями:

Перехват данных с USB устройств класса HID
Доброго всем времени суток! Как перехватить поток данных с USB устройства, которое относится к...

Как вернуть мышь в HID? (диспетчер устройств)
Здравствуйте! я владелец мышки от razer (deathadder edition). раньше был синапс второй,но он...

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

А в чем удобнее писать?
Добрый день! У меня собственно вопрос, в чем на ваше усмотрение удобнее писать на HTML5 и CSS3? ...

Как работает USB HID?
Добрый день. Не могу понять, как работает USB HID на STM32F4. Смотрел примеры от Кайла, от ST,...

22
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
Когда массив в три с лишним сотни значений (вот как у меня сейчас), хочется удобства записи
И было бы замечательно оформить ваш бесценный опыт в конфиги HID Dessriptor Tool
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
Код:
char desc=[....];
const int sizeDesc = sizeof(desc)/sizeof(desc[0]);

#define SIZE_OF_HID_DESCRIPTOR sizeDesc

Опять упираемся в то, что на этапе препроцессора sizeDesc ещё неизвестен. Его развернёт только компилятор. А на этапе препроцессора там, скорее всего, будет 0, ибо "неизвестный науке зверь".
m0Roy
11.12.2016, 18:03 10
Цитата Сообщение от vt340
Цитата Сообщение от m0Roy
Когда массив в три с лишним сотни значений (вот как у меня сейчас), хочется удобства записи
И было бы замечательно оформить ваш бесценный опыт в конфиги HID Dessriptor Tool
Добьюсь работы - выложу всё полностью. Пока упёрся в то, что на виртуальной машине это отлаживать не получается, она эмулирует 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
Dessriptor Tool не в курсе спецификации HID Sensor
Вот именно про это я и говорю - добавить upg-файл для hid simsor в dessriptor tool
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
Цитата Сообщение от Stiit.mi
Код:
char desc=[....];
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
Цитата Сообщение от m0Roy
Dessriptor Tool не в курсе спецификации HID Sensor
Вот именно про это я и говорю - добавить upg-файл для hid simsor в dessriptor tool
Не думаю, что это реально. Как я говорил, софт очень убогий и в частности многобайтовые последовательности он не понимает. Впечатление, что это писал студент на коленке.
Ну или я не разобрался и не понимаю, как запихнуть туда 5-байтовые последовательности спецификации HID Sensor с модификаторами.

Вообще не первый раз встречаю подобное. Казалось бы, серьёзная организация - и ужасный, кривейший софт. Никогда не забуду, какие пляски с бубном мне приходилось устраивать вокруг софта для регистрации штрих-кодов EAN, например. На этом фоне даже наши налоговые и пенсионные со своими Paradox-based софтинами кажутся милашками, хотя та ещё жуть во мраке.
m0Roy
11.12.2016, 23:07 16
Цитата Сообщение от Stiit.mi
Цитата Сообщение от m0Roy
Цитата Сообщение от Stiit.mi
Код:
char desc=[....];
const int sizeDesc = sizeof(desc)/sizeof(desc[0]);

#define SIZE_OF_HID_DESCRIPTOR sizeDesc
Опять упираемся в то, что на этапе препроцессора sizeDesc ещё неизвестен. Его развернёт только компилятор. А на этапе препроцессора там, скорее всего, будет 0, ибо "неизвестный науке зверь".
зато компилятор заменит все на константу, какая разница?

Заменит, да слишком поздно. Проинициализировать константный массив этим не удастся.

Код
#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
Цитата Сообщение от Stiit.mi
зато компилятор заменит все на константу, какая разница?
Заменит, да слишком поздно. Проинициализировать константный массив этим не удастся.

Одну константу можно, а другую низзя? ))

#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
А так придётся скармливать массив компилятору уже три раза. Жуткий костыль, я считаю.
Да хоть 10 раз, на времени компиляции это скажется незначительно, на времени выполнения не скажется абсолютно, код станет немного понятнее.
Ограничения препроцессора это, конечно, неудобно, придется городить костыли. Но всяко лучше собирать за 1 проход, чем использовать пред-препроцессор, вычисляющий размер массива.
0
m0Roy
12.12.2016, 00:58 19
Цитата Сообщение от Stiit.mi
#define SIZE_OF_HID_DESCRIPTOR (sizeof(desc)/sizeof(desc[0]))
Вот так можно, согласен. Это просто макрос, который обрабатывает уже компилятор, а не препроцессор.
Но мне тогда не очень понятно, почему так не сделали в библиотеке V-USB.

[QUOTE="SOKPOWIHIU"][QUOTE="Цитата:[/QUOTE]
А так придётся скармливать массив компилятору уже три раза. Жуткий костыль, я считаю.
Да хоть 10 раз, на времени компиляции это скажется незначительно, на времени выполнения не скажется абсолютно, код станет немного понятнее.
Ограничения препроцессора это, конечно, неудобно, придется городить костыли. Но всяко лучше собирать за 1 проход, чем использовать пред-препроцессор, вычисляющий размер массива.
Не думаю, что код будет понятнее.
Что касается процесса - мы и так при сборке сначала компилируем пачку сырцов, только потом собираем всё воедино. Ещё один шажок, избавляющий от костылей, мне показался предпочтительнее.
0 / 0 / 0
Регистрация: 11.07.2014
Сообщений: 116
12.12.2016, 02:06 20
Но мне тогда не очень понятно, почему так не сделали в библиотеке V-USB.
Скорее всего, предполагали, что часто этим пользоваться не придется.
Что касается процесса - мы и так при сборке сначала компилируем пачку сырцов, только потом собираем всё воедино. Ещё один шажок, избавляющий от костылей, мне показался предпочтительнее.
Удастся ли подобрать стандартную утилиту для этой задачи? И есть ли в этом смысл когда этого достаточно легко избежать.
0
12.12.2016, 02:06
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.12.2016, 02:06
Помогаю со студенческими работами здесь

Как работать с USB HID-class ?
Кто бы научил как с ним работать?

Какими инструментами java удобнее писать 2d игры?
Привет! Подскажите, какими инструментами java пользоваться для написания 2d (плоских) игр? Спасибо

HID Class на V-USB (статья USB для AVR. Часть 2.)
Здравствуйте. Решил перейти от библиотеки Libusb на HIDlibrary и как раз нашел эту статью. Но...

USB для AVR. Часть 2. HID Class на V-USB
Прочитал статью &quot;USB для AVR. Часть 2. HID Ctoss на V-USB&quot;, решил собрать все по примеру и все...

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


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

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