Предел полезной нагрузки исходящего пакета Teensy 3.2 8 байтов - PullRequest
1 голос
/ 17 апреля 2020

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

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

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

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

- Обновление -

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

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

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

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

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

Я использую дескриптор конечной точки , относящийся к интерфейсу с полем bInterfaceClass, назначенным 3 (HID). В этом дескрипторе конечной точки, который первоначально использовался для эмулятора сенсорного экрана Teensy Lib, я установил wMaxPacketSize на 11. Первоначально он был установлен на 8. Эти интерфейс , HID интерфейс , дескрипторы конечной точки определяются, если доступен макрос 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 и 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 (Generi c Desktop) на 0x0d (Digitizer), и теперь мой курсор на Linux перемещается. На Windows драйвер не удалось установить, к сожалению.

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

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

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

- Обновление -

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

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

Original 3M device

А вот дескрипторы подросткового возраста Teensy 3M emulator

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

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

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

enter image description here

Есть ли какие-то тонкие вещи, касающиеся устройств без HID? Как сделать так, чтобы устройство не было HID?

1 Ответ

0 голосов
/ 21 апреля 2020

Вы замечаете, что здесь никто не отвечает на ваш вопрос? Даже не комментарий! В мире очень мало экспертов по 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%. В противном случае, изменяя значение здесь и там, не понимая, что вы делаете, вы просто напрасно тратите свое время.

...