Teensy 3.2 传出数据包有效载荷限制 8 个字节
Posted
技术标签:
【中文标题】Teensy 3.2 传出数据包有效载荷限制 8 个字节【英文标题】:Teensy 3.2 outgoing packet payload limit 8 bytes 【发布时间】: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
值。
下图是原始设备的描述符
这里是teensy的描述
正如您所看到的,唯一的区别在于 bInterfaceClass
的值是青少年 0x03
(端点描述符中的 bInterval
也略有不同,但我认为它的值对于这个问题并不重要)。
如果我尝试摆脱 HID 报告描述符 并使接口等于 0xff
,则设备将无法工作。此外,如果我尝试摆脱具有 1、2、3 索引的不必要的额外接口(来自 teensy),它也不起作用。
下图显示了只有一个 interface 和 endpoint 作为原始设备提供的结果,请参见第一张图片(深色)。并且字段bInterfaceClass
设置为0xff
供应商特定。除了端点没有对USB_INTERRUPT in
的响应外,与主机的通信看起来很正常。而原设备有响应。
关于非 HID 设备有什么微妙之处吗?如何使设备成为非HID设备?
【问题讨论】:
已更新,感谢回复 【参考方案1】:您是否注意到这里没有人回答您的问题?连评论都没有!世界上的 USB 专家非常少。我在最低级别(位和字节)上使用 USB 工作了一年多,我学到了很多东西。对于困难的部分,我不得不从 Beagle 购买昂贵的 USB 分析仪。这是一项非常艰苦的工作,因为您根本无法从任何人那里获得 USB 问题的帮助。 Paul Stoffregen(谁知道)将没有时间帮助您解决这个问题。他忙于自己的事情。他几乎不回答论坛上的问题。
1:
您是正确的,低速设备最多允许 8 个字节,而全速设备最多允许 64 个字节。
2:
如果我理解正确,您使用 Teensyduino 的触摸屏描述符来模拟 3M 触摸屏?这是错误的。如果您想模拟 3M 触摸屏,您必须使用与真正的 3M 触摸屏完全相同的描述符。这是唯一保证您的模拟器在使用与真正的 3M 触摸屏相同的驱动程序的所有操作系统上都能正常工作。如果您有此触摸屏,请使用软件 USBLyzer 从真正的 3M 触摸屏中提取描述符。
3:
您也可以使用 USBLyzer 来验证您自己的描述符。但是有一个很大的问题:Windows 会记住注册表中的 USB 设备。当您在描述符中进行更改时,您必须始终在您的 Teensy 中分配一个新的 ProductID,以便 Windows 将其检测为新设备。否则,您对描述符的更改将无效或不起作用。
4:
您的主要问题似乎与我在从事此项目时遇到的问题相同:https://www.codeproject.com/Articles/1001891/A-USB-HID-Keyboard-Mouse-Touchscreen-emulator-with
TeensyDuino(由 Paul Stoffregen 编写)中的代码很难理解。他仅出于一个目的优化了代码:使用尽可能少的 RAM 并将所有描述符内容存储在 Teensy 的非易失性存储器中。出于这个原因,他的所有定义都是硬编码的。理解他的代码是一项非常艰巨的工作,更难的是在不破坏代码的情况下对其进行修改。
5:
我将 wMaxPacketSize 设置为 11。
这是错误的。使用原始的 3M 描述符!除此之外,这并不能解决您的问题。这个值只是给司机的信息。它不会影响以 Teensy 代码发送的字节数。
6.
我还添加了我的 USB isr 处理程序...
我不知道为什么要这样做?这不是必需的。
7.
在这里我发现我不能发送超过 8 个字节。如果我尝试发送有效载荷无效。
你在哪里看到的?您在这里缺少信息。您在哪里看到有效载荷是无效的?正如您已经发现的那样,没有限制,因为操纵杆发送超过 8 个字节。
您是否使用 USBLyzer 分析数据包?没有这些信息很难回答。您是否调整了该部分中的值
// **************************************************************
// USB Descriptor Sizes
// **************************************************************
使用 USBlyzer 捕获从真正的 3M 触摸屏发送的数据包,并将它们与您的 Teensy 的数据包进行比较。显然所有的描述符在这样做之前必须是相同的。
我在这玩了大约 2 天,但没有成功。
您将需要远更多时间来学习 USB。您需要大量的编程经验、逆向工程经验以及大量的耐心和智慧。
最重要的是,你首先要研究 Paul Stoffregen 的代码,直到你 100% 理解它。否则在不了解你在做什么的情况下到处改变一个值,你只会浪费你的时间。
【讨论】:
更新问题 现在我拒绝效仿 3M 并选择了 Elo。只需复制每个描述符,它就开始工作,Linux 和 Windows 识别它并安装驱动程序(win),我有指针移动。它具有 HID 报告描述符和 8 字节端点数据包大小。不幸的是,我找不到有关正在使用的协议的文档,但是我查看了 Linux 内核驱动程序源并发现了数据包格式,这很简单……但是校准需要进一步调查……以上是关于Teensy 3.2 传出数据包有效载荷限制 8 个字节的主要内容,如果未能解决你的问题,请参考以下文章
如果我在 C# 中发送 0 有效载荷数据,udp 数据包的大小是多少?