Я хотел бы эмулировать 3M USB контроллер с сенсорным экраном. Я нашел точный протокол и немного изменил исходный код в библиотеке teensy3. Я изменил VendorID и ProductID. Также я добавил свой обработчик USB isr и отправил отчет по протоколу c размером 11 байт. Я использую Wireshark, чтобы понюхать USB и вижу, что могу отправить только 8 байтов. Если я попробую хотя бы 9 байтов, то полезной нагрузки не будет вообще.
Я изменил wMaxPacketSize
в дескрипторе конечной точки. Затем я изменил размер отчета о «давлении» с 8 на 11, но это также не помогло. Я обнаружил, что низкоскоростные устройства позволяют только 8 байтов на пакет. Но здесь автор teensy говорит, что он работает на скорости 12 Мбит / с и поэтому должен поддерживать 64 байта.
Может кто-нибудь сказать мне, где я не прав? Как заставить его отправлять более 8 байтов одновременно?
Я тусуюсь с этим около 2 дней безуспешно.
- Обновление -
- Почему вы хотите изменить количество байтов?
Как я уже сказал, мне нужно сделать эмулятор сенсорного экрана 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](https://i.stack.imgur.com/D9NnD.png)
А вот дескрипторы подросткового возраста ![Teensy 3M emulator](https://i.stack.imgur.com/pRNms.png)
Как вы можете видеть, единственная разница заключается в значении bInterfaceClass
для подростка 0x03
(также bInterval
в дескрипторе конечной точки немного отличается, но я полагаю, что это значение не имеет значения для этой проблемы) .
Если я попытаюсь избавиться от дескриптора отчета HID и сделать интерфейс равным 0xff
, устройство не будет работать. Также, если я попытаюсь избавиться от ненужных дополнительных интерфейсов (которые приходят от подростка) с 1, 2, 3 индексами, это не сработает.
На следующем рисунке показан результат, где есть только один интерфейс и конечная точка , которую предоставляет оригинальное устройство, см. Первый pi c (темный). И поле bInterfaceClass
установлено на 0xff
Указывается поставщик c. Связь с хостом выглядит нормально, за исключением того, что нет ответа на USB_INTERRUPT in
от конечной точки. В то время как исходное устройство имеет ответ.
![enter image description here](https://i.stack.imgur.com/E22bv.png)
Есть ли какие-то тонкие вещи, касающиеся устройств без HID? Как сделать так, чтобы устройство не было HID?