【发布时间】:2020-07-31 11:30:24
【问题描述】:
我想模拟 3M USB 触摸屏控制器。我找到了确切的协议并稍微更改了 teensy3 库中的源代码。我更改了 VendorID 和 ProductID。我还添加了我的 USB isr 处理程序并发送大小为 11 字节的协议特定报告。我使用 Wireshark 嗅探 USB,我发现我只能发送 8 个字节。如果我尝试 9 字节,则根本没有有效负载。
我在端点描述符中更改了wMaxPacketSize。然后我将“压力”报告的大小从 8 更改为 11,但这也无济于事。我发现低速设备每个数据包只允许 8 个字节。但是here teensy 的作者告诉它,它以 12Mbit/s 的速度运行,因此应该支持 64 字节。
谁能告诉我我哪里错了?如何让它一次发送超过 8 个字节?
我在这玩了大约 2 天,但没有成功。
-- 更新--
- 为什么要更改字节数?
正如我所说,我需要制作一个 3M 触摸屏的模拟器。因此,它有自己的协议,您可以查看规范 here。第 18 页描述了触摸发生时发送给主机的触摸报告。它的大小是 11 个字节。
我更改了usb_touch.c 中定义的void usb_touchscreen_update_callback(void) 以使其发送必要的结构(参考spec 第18 页)。
在这里我发现我不能发送超过 8 个字节。如果我尝试发送有效载荷无效。
- 您使用的是什么描述符?
我使用与 interface 相关的 端点描述符,其中 bInterfaceClass 字段分配了 3 (HID)。在这个最初由 teensy lib 用于触摸屏模拟器的端点描述符中,我将 wMaxPacketSize 设置为 11。最初它设置为 8。这些 interface、HID 接口、endpoint 如果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宏被header设置为11。
进一步调查原因我发现操纵杆有 12 字节的数据包长度,它确实在具有相同的 interface、HID 接口 和 endpoint 的情况下发送它们em> 像触摸屏一样的描述符。所以看起来它们只是在 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(通用桌面)更改为 0x0d(数字化仪),现在我的光标在 Linux 移动上。不幸的是,Windows 驱动程序无法安装。
此外,由于原始设备只有一个 interface 和一个 ,因此需要将触摸屏 interface 更改为 0 并将 endpoint 更改为 1 >端点。
但无论如何我仍然不知道为什么第一个 HID 报告描述符 阻止发送超过 8 个字节。所以我最终阅读了这篇文章https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/。
我也不需要知道关于 USB 的一切。我只需要理解的水平就可以让这个模拟器正常工作。
-- 更新--
我在 Linux 上,所以我使用 Wireshark。但问题是这个3M原装设备不是HID设备,所以它没有HID报告描述符。该设备仅填充一个标记为供应商特定的接口。字段bInterfaceClass 具有0xff 值。
下图是原始设备的描述符
正如您所看到的,唯一的区别在于 bInterfaceClass 的值是青少年 0x03 (端点描述符中的 bInterval 也略有不同,但我认为它的值对于这个问题并不重要)。
如果我尝试摆脱 HID 报告描述符 并使接口等于 0xff,则设备将无法工作。此外,如果我尝试摆脱具有 1、2、3 索引的不必要的额外接口(来自 teensy),它也不起作用。
下图显示了只有一个 interface 和 endpoint 作为原始设备提供的结果,请参见第一张图片(深色)。并且字段bInterfaceClass 设置为0xff 供应商特定。除了端点没有对USB_INTERRUPT in 的响应外,与主机的通信看起来很正常。而原设备有响应。
关于非 HID 设备有什么微妙之处吗?如何使设备成为非HID设备?
【问题讨论】:
-
已更新,感谢回复
标签: usb touchscreen teensy