使用 ioctl 读取 USB 失败,因为“值对于定义的数据类型来说太大”

问题描述 投票:0回答:3

我正在尝试使用 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 的误解,或者解释一下关于“值对于定义的数据类型来说太大”的错误吗?

android serial-port usb ioctl ftdi
3个回答
2
投票

我找到了解决办法。看来这个错误 EOVERFLOW 可以通过指定等于端点最大数据包大小的缓冲区大小来修复。这解决了我的问题。


1
投票

我最近也遇到了这个错误,感谢@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 字节对我来说很有效,旧设备似乎仍然可以正常工作。


0
投票

你可以修改缓冲区,首先检查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

© www.soinside.com 2019 - 2024. All rights reserved.