Ограничение полезной нагрузки исходящего пакета Teensy 3.2 8 байт

Я хотел бы эмулировать контроллер сенсорного экрана 3M USB. Я нашел точный протокол и немного изменил исходный код в библиотеке teensy3. Я изменил VendorID и ProductID. Также я добавил свой обработчик USB isr и отправил отчет по конкретному протоколу размером 11 байт. Я использую Wireshark для прослушивания USB и вижу, что могу отправить только 8 байт. Если я попробую даже 9 байт, полезной нагрузки вообще не будет.

Я изменил wMaxPacketSize в дескрипторе конечной точки. Затем я изменил размер отчета «давление» с 8 на 11, но это тоже не помогло. Я обнаружил, что низкоскоростные устройства разрешают только 8 байт на пакет. Но здесь автор тинси рассказывает что он работает на скорости 12 Мбит/с и поэтому должен поддерживать 64 байта.

Может ли кто-нибудь сказать мне, где я ошибаюсь? Как заставить его отправлять более 8 байт одновременно?

Я тусуюсь с этим около 2 дней без успеха.

-- Обновить--

  1. Почему вы хотите изменить количество байтов?

Как я уже сказал, мне нужно сделать эмулятор тачскрина 3М. Итак, у него есть собственный протокол, вы можете увидеть спецификацию здесь. Страница 18 описывает отчет о касании, отправляемый хосту при касании. Его размер составляет 11 байт.

Я изменил void usb_touchscreen_update_callback(void), определенный в usb_touch.c, чтобы он отправлял необходимую структуру (ссылка на spec стр. 18).

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

  1. Какой дескриптор вы используете?

Я использую дескриптор конечной точки, относящийся к интерфейсу с bInterfaceClass полем, присвоенным 3 (HID). В этом дескрипторе конечной точки, который первоначально использовался для эмулятора сенсорного экрана teensy lib, я установил wMaxPacketSize на 11. Первоначально он был установлен на 8. Эти interface, HID interface, дескрипторы конечной точки определяются, если доступен макрос MULTITOUCH_INTERFACE.

#ifdef MULTITOUCH_INTERFACE
        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                                      // bLength
        4,                                      // bDescriptorType
        MULTITOUCH_INTERFACE,                   // bInterfaceNumber
        0,                                      // bAlternateSetting
        1,                                      // bNumEndpoints
        0x03,                                   // bInterfaceClass (0x03 = HID)
        0x00,                                   // bInterfaceSubClass
        0x00,                                   // bInterfaceProtocol
        0,                                      // iInterface
        // HID interface descriptor, HID 1.11 spec, section 6.2.1
        9,                                      // bLength
        0x21,                                   // bDescriptorType
        0x11, 0x01,                             // bcdHID
        0,                                      // bCountryCode
        1,                                      // bNumDescriptors
        0x22,                                   // bDescriptorType
        LSB(sizeof(multitouch_report_desc)),    // wDescriptorLength
        MSB(sizeof(multitouch_report_desc)),
        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
        7,                                      // bLength
        5,                                      // bDescriptorType
        MULTITOUCH_ENDPOINT | 0x80,             // bEndpointAddress
        0x03,                                   // bmAttributes (0x03=intr)
        MULTITOUCH_SIZE, 0,                     // wMaxPacketSize
        1,                                      // bInterval
#endif // KEYMEDIA_INTERFACE

Есть макрос MULTITOUCH_SIZE, в заголовке которого установлено значение 11.

Дальнейшее расследование привело к тому, что я обнаружил, что джойстик имеет длину пакета 12 байт, и он действительно отправляет их, имея те же дескрипторы interface, HID interface и endpoint. как у сенсорного экрана. Похоже, они отличаются только дескрипторами отчетов HID.

Этот дескриптор отчета HID относится к сенсорному экрану

static uint8_t multitouch_report_desc[] = {
        0x05, 0x0D,                     // Usage Page (Digitizer)
        0x09, 0x04,                     // Usage (Touch Screen)
        0xa1, 0x01,                     // Collection (Application)
        0x09, 0x22,                     //   Usage (Finger)
        0xA1, 0x02,                     //   Collection (Logical)
        0x09, 0x42,                     //     Usage (Tip Switch)
        0x15, 0x00,                     //     Logical Minimum (0)
        0x25, 0x01,                     //     Logical Maximum (1)
        0x75, 0x01,                     //     Report Size (1)
        0x95, 0x01,                     //     Report Count (1)
        0x81, 0x02,                     //     Input (variable,absolute)
        0x09, 0x51,                     //     Usage (Contact Identifier)
        0x25, 0x7F,                     //     Logical Maximum (127)
        0x75, 0x07,                     //     Report Size (7)
        0x95, 0x01,                     //     Report Count (1)
        0x81, 0x02,                     //     Input (variable,absolute)
        0x09, 0x30,                     //     Usage (Pressure)
        0x26, 0xFF, 0x00,               //     Logical Maximum (255)
        0x75, 0x0b,                     //     Report Size (11)
//        0x75, 0x08,                     //     Report Size (8)
        0x95, 0x01,                     //     Report Count (1)
        0x81, 0x02,                     //     Input (variable,absolute)
        0x05, 0x01,                     //     Usage Page (Generic Desktop)
        0x09, 0x30,                     //     Usage (X)
        0x09, 0x31,                     //     Usage (Y)
        0x26, 0xFF, 0x7F,               //     Logical Maximum (32767)
        0x65, 0x00,                     //     Unit (None)  <-- probably needs real units?
        0x75, 0x10,                     //     Report Size (16)
        0x95, 0x02,                     //     Report Count (2)
        0x81, 0x02,                     //     Input (variable,absolute)
        0xC0,                           //   End Collection
        0x05, 0x0D,                     //   Usage Page (Digitizer)
        0x27, 0xFF, 0xFF, 0, 0,         //   Logical Maximum (65535)
        0x75, 0x10,                     //   Report Size (16)
        0x95, 0x01,                     //   Report Count (1)
        0x09, 0x56,                     //   Usage (Scan Time)
        0x81, 0x02,                     //   Input (variable,absolute)
        0x05, 0x0D,                     //   Usage Page (Digitizers)
        0x09, 0x55,                     //   Usage (Contact Count Maximum)
        0x25, MULTITOUCH_FINGERS,       //   Logical Maximum (10)
        0x75, 0x0b,                     //   Report Size (11)
//        0x75, 0x08,                     //   Report Size (8)
        0x95, 0x01,                     //   Report Count (1)
        0xB1, 0x02,                     //   Feature (variable,absolute)
        0xC0                            // End Collection
};

А этот для джойстика

static uint8_t joystick_report_desc[] = {
        0x05, 0x01,                     // Usage Page (Generic Desktop)
        0x09, 0x04,                     // Usage (Joystick)
        0xA1, 0x01,                     // Collection (Application)
        0x15, 0x00,                     //   Logical Minimum (0)
        0x25, 0x01,                     //   Logical Maximum (1)
        0x75, 0x01,                     //   Report Size (1)
        0x95, 0x20,                     //   Report Count (32)
        0x05, 0x09,                     //   Usage Page (Button)
        0x19, 0x01,                     //   Usage Minimum (Button #1)
        0x29, 0x20,                     //   Usage Maximum (Button #32)
        0x81, 0x02,                     //   Input (variable,absolute)
        0x15, 0x00,                     //   Logical Minimum (0)
        0x25, 0x07,                     //   Logical Maximum (7)
        0x35, 0x00,                     //   Physical Minimum (0)
        0x46, 0x3B, 0x01,               //   Physical Maximum (315)
        0x75, 0x04,                     //   Report Size (4)
        0x95, 0x01,                     //   Report Count (1)
        0x65, 0x14,                     //   Unit (20)
        0x05, 0x01,                     //   Usage Page (Generic Desktop)
        0x09, 0x39,                     //   Usage (Hat switch)
        0x81, 0x42,                     //   Input (variable,absolute,null_state)
        0x05, 0x01,                     //   Usage Page (Generic Desktop)
        0x09, 0x01,                     //   Usage (Pointer)
        0xA1, 0x00,                     //   Collection ()
        0x15, 0x00,                     //     Logical Minimum (0)
        0x26, 0xFF, 0x03,               //     Logical Maximum (1023)
        0x75, 0x0A,                     //     Report Size (10)
        0x95, 0x04,                     //     Report Count (4)
        0x09, 0x30,                     //     Usage (X)
        0x09, 0x31,                     //     Usage (Y)
        0x09, 0x32,                     //     Usage (Z)
        0x09, 0x35,                     //     Usage (Rz)
        0x81, 0x02,                     //     Input (variable,absolute)
        0xC0,                           //   End Collection
        0x15, 0x00,                     //   Logical Minimum (0)
        0x26, 0xFF, 0x03,               //   Logical Maximum (1023)
        0x75, 0x0A,                     //   Report Size (10)
        0x95, 0x02,                     //   Report Count (2)
        0x09, 0x36,                     //   Usage (Slider)
        0x09, 0x36,                     //   Usage (Slider)
        0x81, 0x02,                     //   Input (variable,absolute)
        0xC0                            // End Collection
};

Затем я заменил первый на второй, и после этого я получил полные 11 байтов, отправленных через эту конечную точку. Затем я изменил первый байт 0x01 (Generic Desktop) на 0x0d (Digitizer), и теперь мой курсор перемещается по Linux. К сожалению, в Windows драйвер не устанавливается.

Также необходимо было изменить интерфейс тачскрина на 0 и конечную точку на 1, поскольку исходное устройство имеет только один интерфейс и одну конечную точку<. /эм>.

Но в любом случае я до сих пор не знаю, почему первый дескриптор отчета HID не позволяет отправлять более 8 байт. В итоге я прочитал эту статью https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/.

Также мне не нужно знать все о USB. Мне просто нужен уровень понимания, чтобы этот эмулятор работал правильно.

-- Обновить--

У меня Linux, поэтому я использую Wireshark. Но проблема в том, что это оригинальное устройство 3M не является устройством HID, поэтому у него нет дескриптора отчета HID. Устройство заполняет только один интерфейс, помеченный как Специфический для поставщика. Поле bInterfaceClass имеет значение 0xff.

На картинке ниже дескрипторы оригинального устройства

Оригинальное устройство 3M

А вот дескрипторы тинси Эмулятор Teensy 3M

Как вы можете видеть, единственная разница заключается в значении bInterfaceClass для teensy 0x03 (также немного отличается bInterval в дескрипторе конечной точки, но я полагаю, что это значение не имеет значения для этой проблемы).

Если я попытаюсь избавиться от дескриптора отчета HID и сделать интерфейс равным 0xff, устройство не будет работать. Также, если я попытаюсь избавиться от ненужных дополнительных интерфейсов (которые исходят от teensy) с 1, 2, 3 индексами, это не сработает.

На следующем рисунке показан результат, когда есть только один интерфейс и конечная точка, поскольку исходное устройство обеспечивает см. первое изображение (темное). А в поле bInterfaceClass установлено значение 0xff Специфично для поставщика. Связь с хостом выглядит нормально, за исключением того, что нет ответа на USB_INTERRUPT in от конечной точки. В то время как оригинальное устройство имеет ответ.

введите здесь описание изображения

Есть ли какие-то тонкости в отношении не HID-устройств? Как сделать устройство не HID-устройством?


person 4xy    schedule 17.04.2020    source источник
comment
Обновлено, спасибо за ответ   -  person 4xy    schedule 18.04.2020


Ответы (1)


Вы заметили, что здесь никто не отвечает на ваш вопрос? Даже без комментариев! В мире очень мало специалистов по USB. Я работал более года с USB на самом низком уровне (биты и байты) и многому научился. А для сложных частей пришлось купить дорогой USB анализатор от Beagle. Это очень тяжелая работа, потому что вы просто ни от кого не получите помощи в решении ваших проблем с USB. И Пауль Штоффреген (кто его знает) не успеет вам в этом помочь. Он занят своими делами. Он почти не отвечает на вопросы на своем форуме.

1:

Вы правы, что низкоскоростные устройства позволяют использовать максимум 8 байтов, а полноскоростные — 64 байта.

2:

Если я вас правильно понимаю, вы используете дескриптор сенсорного экрана Teensyduino для эмуляции сенсорного экрана 3M? Это не верно. Если вы хотите эмулировать сенсорный экран 3M, вы ДОЛЖНЫ использовать те же дескрипторы, что и настоящий сенсорный экран 3M. Это единственная гарантия того, что ваш эмулятор будет работать одинаково во всех операционных системах с использованием тех же драйверов, что и настоящий сенсорный экран 3M. Если у вас есть этот сенсорный экран, используйте программное обеспечение USBLyzer, чтобы извлечь дескрипторы из настоящего сенсорного экрана 3M.

3:

Вы также можете использовать USBLyzer для проверки собственных дескрипторов. НО есть очень большая загвоздка: Windows запоминает USB-устройства в реестре. Когда вы вносите изменения в дескриптор, вы всегда должны назначать новый ProductID в своем Teensy, чтобы Windows определяла его как новое устройство. В противном случае ваши изменения в дескрипторах не будут иметь никакого эффекта или не будут работать.

4:

Ваша основная проблема, похоже, та же, что и у меня, когда я работал над этим проектом: https://www.codeproject.com/Articles/1001891/A-USB-HID-Keyboard-Mouse-Touchscreen-emulator-with

Код в TeensyDuino (написанный Полом Стоффрегеном) сложен для понимания. Он оптимизировал код только с одной целью: использовать как можно меньше оперативной памяти и хранить все дескрипторы в энергонезависимой памяти Teensy. По этой причине все его определения жестко закодированы. Это очень тяжелая работа, чтобы понять его код и еще труднее изменить его, не сломав.

5:

Я установил для wMaxPacketSize значение 11.

Это не верно. Используйте оригинальный дескриптор 3M! Кроме того, это не решает вашу проблему. Это значение является только информацией для драйвера. Это не влияет на количество байтов, отправляемых в коде Teensy.

6.

Также я добавил свой обработчик USB isr...

Я не знаю, зачем это делать? В этом нет необходимости.

7.

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

Где ты это видишь? Вам здесь не хватает информации. Где вы видите, что полезная нагрузка недействительна? Как вы уже обнаружили, ограничений НЕТ, потому что джойстик отправляет более 8 байтов.

Вы анализировали пакеты с помощью USBLyzer? Без этой информации сложно ответить. Вы адаптировали значения в разделе

// **************************************************************
//   USB Descriptor Sizes
// **************************************************************

Используйте USBlyzer для захвата пакетов, отправленных с реального сенсорного экрана 3M, и сравнения их с пакетами вашего Teensy. Очевидно, что перед этим ВСЕ дескрипторы должны быть идентичными.

Я тусуюсь с этим около 2 дней без успеха.

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

Самое главное, чтобы вы сначала изучили код Пауля Стоффрегена, пока не поняли его на 100%. В противном случае, меняя значение тут и там, не понимая, что вы делаете, вы просто потратите свое время.

person Elmue    schedule 21.04.2020
comment
Обновил вопрос - person 4xy; 26.04.2020
comment
Пока отказался от эмуляции 3М и взял Эло. Просто продублировал каждый дескриптор, и он начал работать, Linux и Windows распознают его и устанавливают драйверы (выигрыш), и у меня движется указатель. Он имеет дескриптор отчета HID и размер пакета конечной точки 8 байт. К сожалению, я не смог найти документацию по используемому протоколу, но я посмотрел исходный код драйвера ядра Linux и выяснил формат пакета, это тривиально... но калибровка требует дальнейшего изучения... - person 4xy; 02.05.2020