Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: hid-report
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам > RS232/LPT/USB/PCMCIA/FireWire
_lukash_
Всем привет!

Разбираюсь с USB HID (по usb.org и книге "Агуров Интерфейс USB Практика использования и программирования"), уже почти все понял, проблема ток с hid-report'ом...
Создаю Alphanumeric Display report (0х14), но не понимаю значение некоторых элементов репорта. В частности - объясните плз для чего нужны USAGE - и почему их так много в репорте? Т.е. я должен создать USAGE на каждую используемую функцию из спецификации HID Usage Tables?

Составляю дескриптор репорта с помощью HID descriptor Tool, там и пример для Alphanumeric Display есть, но ведь там USAGE не на все возможные функции прописаны:

Код
char ReportDescriptor[136] = {
    0x05, 0x14,                    // USAGE_PAGE (Alphnumeric Display)
    0x09, 0x01,                    // USAGE (Alphanumeric Display)
    0x15, 0x00,                    // LOGICAL_MINIMUM (0)
    0xa1, 0x02,                    // COLLECTION (Logical)
    0x09, 0x20,                    //   USAGE (Display Attributes Report)
    0xa1, 0x02,                    //   COLLECTION (Logical)
    0x09, 0x35,                    //     USAGE (Rows)
    0x09, 0x36,                    //     USAGE (Columns)
    0x09, 0x3d,                    //     USAGE (Character Width)
    0x09, 0x3e,                    //     USAGE (Character Height)
    0x85, 0x01,                    //     REPORT_ID (1)
    0x25, 0x1f,                    //     LOGICAL_MAXIMUM (31)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x95, 0x04,                    //     REPORT_COUNT (4)
    0xb1, 0x03,                    //     FEATURE (Cnst,Var,Abs)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x09, 0x21,                    //     USAGE (ASCII Character Set)
    0x09, 0x22,                    //     USAGE (Data Read Back)
    0x09, 0x29,                    //     USAGE (Vertical Scroll)
    0xb1, 0x03,                    //     FEATURE (Cnst,Var,Abs)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0xb1, 0x03,                    //     FEATURE (Cnst,Var,Abs)
    0xc0,                          //   END_COLLECTION
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x25, 0x02,                    //   LOGICAL_MAXIMUM (2)
    0x09, 0x2d,                    //   USAGE (Display Status)
    0xa1, 0x02,                    //   COLLECTION (Logical)
    0x09, 0x2e,                    //     USAGE (Stat Not Ready)
    0x09, 0x2f,                    //     USAGE (Stat Ready)
    0x09, 0x30,                    //     USAGE (Err Not a loadable character)
    0x81, 0x40,                    //     INPUT (Data,Ary,Abs,Null)
    0xc0,                          //   END_COLLECTION
    0x09, 0x32,                    //   USAGE (Cursor Position Report)
    0xa1, 0x02,                    //   COLLECTION (Logical)
    0x85, 0x02,                    //     REPORT_ID (2)
    0x75, 0x04,                    //     REPORT_SIZE (4)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x25, 0x0f,                    //     LOGICAL_MAXIMUM (15)
    0x09, 0x34,                    //     USAGE (Column)
    0xb1, 0x22,                    //     FEATURE (Data,Var,Abs,NPrf)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x09, 0x33,                    //     USAGE (Row)
    0xb1, 0x22,                    //     FEATURE (Data,Var,Abs,NPrf)
    0xc0,                          //   END_COLLECTION
    0x09, 0x2b,                    //   USAGE (Character Report)
    0xa1, 0x02,                    //   COLLECTION (Logical)
    0x85, 0x03,                    //     REPORT_ID (3)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x04,                    //     REPORT_COUNT (4)
    0x25, 0x7e,                    //     LOGICAL_MAXIMUM (126)
    0x09, 0x2c,                    //     USAGE (Display Data)
    0xb2, 0x02, 0x01,              //     FEATURE (Data,Var,Abs,Buf)
    0xc0,                          //   END_COLLECTION
    0x85, 0x04,                    //   REPORT_ID (4)
    0x09, 0x3b,                    //   USAGE (Font Report)
    0xa1, 0x02,                    //   COLLECTION (Logical)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x7e,                    //     LOGICAL_MAXIMUM (126)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x09, 0x2c,                    //     USAGE (Display Data)
    0x91, 0x02,                    //     OUTPUT (Data,Var,Abs)
    0x95, 0x05,                    //     REPORT_COUNT (5)
    0x09, 0x3c,                    //     USAGE (Font Data)
    0x92, 0x02, 0x01,              //     OUTPUT (Data,Var,Abs,Buf)
    0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION
};


И почему я не могу просто прописать в репорте одну INPUT, и одну OUTPUT (ессно с остальными обязательными элементами)? А в проге для компа просто записывать нужные команды?

Где еще можно почитать про составление hid-report, кроме как на usb.org , книге Агурова, USB masters? Поиск по форуму дает в основном эти ссылки, по ним я и разбирался с HID, сейчас опять по спецификациям из usb.org пытаюсь разобраться...
_lukash_
Пока составил репорт только с одной INPUT и одной OUTPUT, чтоб попробовать получше разобраться:

Код
BYTE __flash ReportDescriptor_HID[] = {
    0x06, 0x00, 0xFF,    // Usage Page (Vendor Defined Page 1)
    0x09, 0x01,        // Usage (Vendor Usage 1)
    0xa1, 0x01,        // Collection (Application)
    0x15, 0x00,        //   Logical Minimum (0)
    0x26, 0xFF, 0x00,                    //   Logical Maximum (255)
    0x75, 0x08,        //   Report Size (8)
           0x95, 0x01,        //   Report Count (1)
                0x09, 0x01,        //   Usage (Vendor Usage 1)
    0x81, 0x02,        //   Input (Data, Variable, Absolute, Bit Field)
                0x09, 0x02,        //   Usage (Vendor Usage 2)
    0x91, 0x02,        //   Output (Data, Variable, Absolute, Bit Field)
    0xc0            // End Collection
};

Также сделал вот такой дескриптор конфигурации, использую конечную точку EP1:
Код
// Configuration descriptor
USB_CONFIG_DATA __flash ConfigurationDescriptor_HID = {
    {                // configuration descriptor
    sizeof(USB_CONFIGURATION_DESCRIPTOR), // bLength
    TYPE_CONFIGURATION_DESCRIPTOR,    // bDescriptorType
    sizeof(USB_CONFIG_DATA),        // wTotalLength
    1,                // bNumInterfaces
    1,                // bConfigurationValue
    0,                // iConfiguration String Index
    0xA0,                // bmAttributes Bus Powered, Remote Wakeup
    0x32                // bMaxPower, 100mA
    },
    {                // interface descriptor
    sizeof(USB_INTERFACE_DESCRIPTOR),       // bLength
    TYPE_INTERFACE_DESCRIPTOR,        // bDescriptorType
    0,                // bInterface Number
    0,                // bAlternateSetting
    2,                // bNumEndpoints
    3,                // bInterfaceClass (HID class)
    0,                // bInterfaceSubClass(Boot subclass)
    0,                // bInterfaceProtocol
    2                // iInterface String Index
    },
    {                // HID descriptor
    sizeof(USB_HID_DESCRIPTOR),        // bLength
    TYPE_HID_DESCRIPTOR,        // bDescriptorType
    0x0100,                // wHIDClassSpecComp
    0,                // bCountry
    1,                // bNumDescriptors
    0x22,                // b1stDescType (Report)
    sizeof(ReportDescriptor_HID)        // w1stDescLength
    },
    {                // endpoint descriptor
    sizeof(USB_ENDPOINT_DESCRIPTOR),    // bLength
    TYPE_ENDPOINT_DESCRIPTOR,        // bDescriptorType
    0x81,                // bEndpoint Address EP1 IN
    0x03,                // bmAttributes - Interrupt
    0x0008,                // wMaxPacketSize
    0x0A                // bInterval (10 ms)
    },
                {                // endpoint descriptor
    sizeof(USB_ENDPOINT_DESCRIPTOR),    // bLength
    TYPE_ENDPOINT_DESCRIPTOR,        // bDescriptorType
    0x01,                // bEndpoint Address EP1 OUT
    0x03,                // bmAttributes - Interrupt
    0x0008,                // wMaxPacketSize
    0x0A                // bInterval (10 ms)
    }
};

Вот эта часть кода находится в главном цикле:
Код
    if (Irq & D11_INT_EP1_IN){
        D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP1_IN, Buffer, 1);
                   //debug('b');
                }
        if (1)
        {
                // заполнить информационные данные
                Buffer[0] = temp;
                            hid_bufsize = 1;

                // отправить буфер
                D11WriteEndpoint(D11_ENDPOINT_EP1_IN, Buffer, hid_bufsize);
        }

    if (Irq & D11_INT_EP1_OUT) {
      D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP1_OUT, Buffer, 1);
       if (1) {
            D11ReadEndpoint(D11_ENDPOINT_EP1_OUT, &Buffer[0]);
                        temp = 2;//Buffer[0];
       }
                  debug('c');
                  debug('c');
    }


По идее, при вызове WriteFile с пользовательского приложения, должно генерироваться D11_INT_EP1_OUT, но этого не происходит (debug- отладка по UART). Сам исходник для отправки/приема данных взял с книги "Агуров Интерфейс USB Практика использования и программирования", исходник на Делфи, добавил туда WriteFile. При вызове WriteFile возвращается ошибка, при ReadFile все корректно читается с устройства. В чем может быть проблема при записи?
Исходник прикрепил, посмотрите плз.
Нажмите для просмотра прикрепленного файла
_lukash_
Хех, разобрался вроде с записью.
Я не правильно буфер для отправки устройству заполнял - в hid-репорте не указывал REPORT_ID, а при отсутствии его по умолчанию REPORT_ID равен 0, если я правильно понял спецификациюsmile.gif
Т.е. первую ячейку буфера устанавливаю в 0, остальные - данные для отправки - тогда все работает!
_lukash_
Разобрался как строится hid-report, и почему там так много USAGE:)

Появилась еще одна небольшая проблема - если добавить FEATURE
0x75, 0x05, // REPORT_SIZE (5)
0x95, 0x04, // REPORT_COUNT (4)
0xb1, 0x03, // FEATURE (Cnst,Var,Abs)
то устройство не работает корректно (“Запуск этого устройства невозможен” в диспетчере устройств), но если при этом REPORT_SIZE установить в 8, то все работает (все значения, которые отличаются от 8 тоже не работают). Но почему так? Ведь 8 должно быть только при установленном "Array" бите, а я использую "Variable"?
arizona
Цитата(_lukash_ @ Jan 11 2008, 00:01) *
Разобрался как строится hid-report, и почему там так много USAGE:)

Появилась еще одна небольшая проблема - если добавить FEATURE
0x75, 0x05, // REPORT_SIZE (5)
0x95, 0x04, // REPORT_COUNT (4)
0xb1, 0x03, // FEATURE (Cnst,Var,Abs)
то устройство не работает корректно (“Запуск этого устройства невозможен” в диспетчере устройств), но если при этом REPORT_SIZE установить в 8, то все работает (все значения, которые отличаются от 8 тоже не работают). Но почему так? Ведь 8 должно быть только при установленном "Array" бите, а я использую "Variable"?


разбирался с джойстиком, так там если задается в дескрипторе, например, 4 кнопки, то нужно отправлять 4 бита. Так не делается, нужно отправлять по байтам, поэтому задается report_size 1 (т.к. состояние кнопки 1 бит - нажата или не нажата), но report_count должен быть 8 (т.к. передается 1 байт)

см еще http://microchip.com.ru/1010/Support/USB%20apps.html
"В нашем случае «газ» это одно 8-и битное значение (report_size = 8, report_count = 1), а состояние кнопок определяется как поле однобитных значений. В примере используется только 2 кнопки, но необходимо выровнять поле до байтовой величины (report_size = 1, report_count = 8). Итого микроконтроллер при запросе данных от компьютера должен передать 2 байта – уровень газа и состояние кнопок"
_lukash_
arizona
Спасибо, понял. Переделал - теперь работает.

Вот что еще интересует - в спецификации HID Usage Tables не сказано какие типы передачи (FEATURE или через прерывания) нужно применять для определенных репортов. Я сделал все на FEATURE, вроде работает корректно, но правильно ли это?

По идее в примере использовались Interrupt посылки только потому, что передавался большой объем данных (в FEATURE посылках максимальный размер поля данных для низкоскоростного устройства (у меня низкоскоростное) не должен превышать 8 байт), но мне не нужно передавать больше 8 байт в одной посылке.

Т.е. я сам выбираю какие типы передачи использовать?
galjoen
Цитата(_lukash_ @ Jan 17 2008, 00:12) *
Вот что еще интересует - в спецификации HID Usage Tables не сказано какие типы передачи (FEATURE или через прерывания) нужно применять для определенных репортов. Я сделал все на FEATURE, вроде работает корректно, но правильно ли это?

Делайте как удобнее. Я использую и то и другое в одном устройстве. FEATURE пользоваться сложнее. И со стороны компьютера, и со стороны устройства. Но этот метод более продвинутый.
FEATURE:
1. Обмен всегда начинается по инициативе компьютера.
2. FEATURE репортов м.б. 254 штуки (Interrupt-ов токо 2, по 1 в каждую сторону). Устойство, получив пакет SETUP, по Report ID (есть в SETUP-ном пакете) уже знает, что будет посылать (принимать).
3. Длина ограничена только размером буфера USB (у USB буфер на контрольный канал вроде-бы 4 кбайта). 8 байт у LowSpeed это размер пакета за кадр USB (1 мсек). А пакетов м.б. несколько. Токо не забывайте про DATA1/DATA0. (Как раз наоборот - у Interrupt токо 1 пакет м.б.).
Interrupt:
1. Interrupt In начинается по инициативе устройства. Interrupt Out - компьютера.
2. Буфера на несколько посылок (кол-во можно изменять) встроены в HID драйвер. Из-за этого данные не теряются даже если задача не активна. Но и проблема с синхронизацией ввода и вывода возникает. Если вам это надо конечно.
3. На компьютере простой readfile (+overlap чтоб не ждать).

По описанию FEATURE c 1 пакетом данных должен выполнятся за 3 мсек. SETUP=1мсек + DATA=1мсек + подтв. чтение/запись=1мсек. А если устойство пошлёт NAK, то след-й пакет от хоста д.б. через 1 мсек. Тоесть max скорость менее 64 кбайт в сек (1 пакет 64 байта в мсек на FullSpeed). Реально всё зависит от южного моста. Заметил, что интеловские чипсеты - соответствуют. А те, которые с АМД процессорами (в часности VIA) - нет. С VIA мой HID - 600 кбайт в секунду качает (Full Speed)! Почти как MassStorage (1000). Жаль только, что рассчитывать на это нельзя. Неизвестно, что у пользователя будет.
_lukash_
galjoen
Спасибо.
_lukash_
Еще вопрос - есть ли какие-то программки для тестирования Alphаnumeric Display? Или в самой Винде (ХР), или отдельно. К примеру, USB джойстик можно потестить в самой ХР.
Или эта 14 страница приводится как "рекомендации" для создания протокола обмена?))
galjoen
Цитата(_lukash_ @ Jan 20 2008, 14:09) *
Еще вопрос - есть ли какие-то программки для тестирования Alphаnumeric Display? Или в самой Винде (ХР), или отдельно. К примеру, USB джойстик можно потестить в самой ХР.

Специально для Alphаnumeric Display наверное нет. На usb.org есть тестовые вообще, и для HID в частности. Рекомендую проверить. Сам когда проверял - был удивлён скоко несоответствий. Одна из программ даже HID-дескриптор отдельно запросила. Хотя по описанию USB, вроде токо вместе с конфигурацией должна. Посмотрел, USB мышка отдельно выдаёт, ну и я начал.
Цитата(_lukash_ @ Jan 20 2008, 14:09) *
Или эта 14 страница приводится как "рекомендации" для создания протокола обмена?))

Это для того, чтоб кто-то, не знакомый ни с вами ни с вашим устройством, написал программу которая Alphаnumeric Display работает - и она-бы сразу с вашим устройством заработала. Ни драйверов ни настройки не потребовав. Вам это надо?
Мне, например, нет. Я Vendor Defined page пользуюсь. С моим устройством токо моя программа работает. А другие пусть лучше и не пытаются.
_lukash_
С usb.org испробовал все кроме той которая больше 100 метров. Но они у меня не работают, или я просто не до конца разобрался еще. А какую из них Вы использовали?

>Вам это надо?
Это мое первое USB устройство, хочу разобраться как следует. А так, то я к нему пишу библиотеку, экспортирующую уже совсем "высокоуровневые" функции.
galjoen
Цитата(_lukash_ @ Jan 22 2008, 01:24) *
С usb.org испробовал все кроме той которая больше 100 метров. Но они у меня не работают, или я просто не до конца разобрался еще. А какую из них Вы использовали?

Давно это было. Года 2 назад. С тех пор компьютер поменял. И забыл многое, в т.ч. названия. Но помню, что у меня тоже в начале не шли. Я сначала USB мышку и USB джойстик научился тестировать. А сам в это время SnoopyPro смотрел, какие запросы там шлются. Пока на них правильно отвечать не начнешь - тестироватся не будет. Ещё помню, что для одной из тестирующих программ W98 установить пришлось.
С тех пор с HID никаких проблем не имел в т.ч. под Linux. Ну и не тестировал ничо.
Цитата(_lukash_ @ Jan 22 2008, 01:24) *
Это мое первое USB устройство, хочу разобраться как следует.

Завидую. Тоже хотел, но не смог из-за недостатка времени. Если, что интересное всплывёт - пишите.
Цитата(_lukash_ @ Jan 22 2008, 01:24) *
А так, то я к нему пишу библиотеку, экспортирующую уже совсем "высокоуровневые" функции.

А ваша библиотека токо с вашим устойством работать будет? Или с Alphаnumeric Display общего вида (чужим)? И как вы его ищете - по VID+PID, или по Usage Page, или по Usage Page + корневая коллекция Usage? Или может ещё как?
_lukash_
ОК, попробую где-то найти корректно работающее USB HID устройство (у меня еще и нет других USB HID типа мышки или еще чего-то), и сначала на нем протестирую, а потом уже дисплей тестить буду. Вдруг че интересного будет, отпишусь

Библиотека скорей всего будет работать ток с моим устройством, т.к. некоторые Usage использую не так, как в спецификации описано. А ищу я его по VID+PID.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.