我正在尝试使用 ioctl 和 USBDEVFS_BULK(在 Android 上本机)读取 USB。我使用的 USB 电缆包含一个 FTDI 芯片,并从 Arduino UNO 发送数据,该数据写入串行。
Android 上的写入似乎总是成功,但读取要么总是失败,要么在一些条目上成功,然后不断失败,并显示“对于定义的数据类型来说值太大”(75)。我使用这个设置进行一个简单的 ping 测试:在 Android 上写入一个字节,一个序列号; Arduino 读取字节并回复相同的序列号。
我不完全确定这个错误是什么意思。我的理解是设备发送的数据多于我传递给 ioctl 的缓冲区可以容纳的数据。我已确保我的 Arduino 仅发回 1 个字节,并且我预计 FTDI 会再发送 2 个字节,总共 3 个字节。即使增加缓冲区大小似乎也无法解决问题。
char mReadData[3];
struct usbdevfs_bulktransfer bulkTransferRead = {
mReadEndpoint, // Endpoint
3, // Length in bytes
0, // Timeout (ms)
mReadData, // Data
};
ret = ioctl(mFd, USBDEVFS_BULK, &bulkTransferRead);
这是我本机使用的代码。如果我尝试使用 Android/Java 代码进行读取和写入(使用bulkTransfer()),我会看到与读取相同的间歇性问题。在 Android 上的 Java 中,我确保在任何写入/读取之前执行以下操作:
1) 复位引脚 2)设置波特率 3)8N1
任何人都可以帮我描述一下我对 FTDI/USB 的误解,或者解释一下关于“值对于定义的数据类型来说太大”的错误吗?
我找到了解决办法。看来这个错误 EOVERFLOW 可以通过指定等于端点最大数据包大小的缓冲区大小来修复。这解决了我的问题。
我最近也遇到了这个错误,感谢@Jary 为我指出了正确的方向。 对于最终在这里寻找最大数据包大小的其他人,请将您的设备插入 Linux 盒子并找到所需的设备和端点:
lsusb -v | grep 'Bus\|bEndpointAddress\|wMaxPacketSize\|idVendor\|idProduct'
输出示例:
Bus 001 Device 027: ID 0451:d109 Texas Instruments, Inc.
idVendor 0x0451 Texas Instruments, Inc.
idProduct 0xd109
bEndpointAddress 0x81 EP 1 IN
wMaxPacketSize 0x0200 1x 512 bytes
bEndpointAddress 0x02 EP 2 OUT
wMaxPacketSize 0x0200 1x 512 bytes
bEndpointAddress 0x82 EP 2 IN
wMaxPacketSize 0x001c 1x 28 bytes
bEndpointAddress 0x83 EP 3 IN
wMaxPacketSize 0x0200 1x 512 bytes
bEndpointAddress 0x03 EP 3 OUT
wMaxPacketSize 0x0200 1x 512 bytes
缓冲区所需的最大数据包大小在端点地址下给出。
有关更多信息,请参阅此页面,其中包含其他有趣的花絮:
批量传输仅支持全速和高速设备。 对于 全速端点,最大批量数据包大小为 8、16、32 或 64 字节长。对于高速端点,最大数据包大小 最长可达 512 字节。 如果数据有效负载低于 最大数据包大小,不需要用零填充。散装 当传输准确时,传输被认为完成 请求的数据量,传输的数据包小于最大值 端点大小,或传输零长度数据包。 (强调我的)
缓冲区需要等于这些大小之一。 将它们设置为任意大或只是其他值(例如 1024 字节)似乎不起作用。 在我的例子中,缓冲区最初是 64 字节,适用于旧设备,但当连接到最大数据包大小为 512 字节的新设备时,它会因 OP 错误而失败。 增加到 512 字节对我来说很有效,旧设备似乎仍然可以正常工作。
你可以修改缓冲区,首先检查sudo ip link show,如果1000个链接或1500增加到:
sudo sysctl -w net.core.rmem_max=26214400 sudo sysctl -w net.core.wmem_max=26214400
验证: 猫 /proc/sys/net/core/rmem_max 猫 /proc/sys/net/core/wmem_max