Я хотел бы эмулировать контроллер сенсорного экрана 3M USB. Я нашел точный протокол и немного изменил исходный код в библиотеке teensy3. Я изменил VendorID и ProductID. Также я добавил свой обработчик USB isr и отправил отчет по конкретному протоколу размером 11 байт. Я использую Wireshark для прослушивания USB и вижу, что могу отправить только 8 байт. Если я попробую даже 9 байт, полезной нагрузки вообще не будет.
Я изменил wMaxPacketSize
в дескрипторе конечной точки. Затем я изменил размер отчета «давление» с 8 на 11, но это тоже не помогло. Я обнаружил, что низкоскоростные устройства разрешают только 8 байт на пакет. Но здесь автор тинси рассказывает что он работает на скорости 12 Мбит/с и поэтому должен поддерживать 64 байта.
Может ли кто-нибудь сказать мне, где я ошибаюсь? Как заставить его отправлять более 8 байт одновременно?
Я тусуюсь с этим около 2 дней без успеха.
-- Обновить--
- Почему вы хотите изменить количество байтов?
Как я уже сказал, мне нужно сделать эмулятор тачскрина 3М. Итак, у него есть собственный протокол, вы можете увидеть спецификацию здесь. Страница 18 описывает отчет о касании, отправляемый хосту при касании. Его размер составляет 11 байт.
Я изменил void usb_touchscreen_update_callback(void)
, определенный в usb_touch.c
, чтобы он отправлял необходимую структуру (ссылка на spec стр. 18).
Здесь я обнаружил, что не могу отправить более 8 байт. Если я вообще попытаюсь отправить пустую полезную нагрузку.
- Какой дескриптор вы используете?
Я использую дескриптор конечной точки, относящийся к интерфейсу с 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
.
На картинке ниже дескрипторы оригинального устройства
Как вы можете видеть, единственная разница заключается в значении bInterfaceClass
для teensy 0x03
(также немного отличается bInterval
в дескрипторе конечной точки, но я полагаю, что это значение не имеет значения для этой проблемы).
Если я попытаюсь избавиться от дескриптора отчета HID и сделать интерфейс равным 0xff
, устройство не будет работать. Также, если я попытаюсь избавиться от ненужных дополнительных интерфейсов (которые исходят от teensy) с 1, 2, 3 индексами, это не сработает.
На следующем рисунке показан результат, когда есть только один интерфейс и конечная точка, поскольку исходное устройство обеспечивает см. первое изображение (темное). А в поле bInterfaceClass
установлено значение 0xff
Специфично для поставщика. Связь с хостом выглядит нормально, за исключением того, что нет ответа на USB_INTERRUPT in
от конечной точки. В то время как оригинальное устройство имеет ответ.
Есть ли какие-то тонкости в отношении не HID-устройств? Как сделать устройство не HID-устройством?