为什么读取不终止我的 USB 设备?

Why does read not terminate for my USB device?

我有一个 USB 设备连接到我的 RaspberryPi 3 B+ (Raspbian Buster Lite 2019-07-10)。我还编写了一个小程序来从 USB 设备读取数据。该设备有一个自定义的、符合 CDC 标准的固件,因此 OS 可以正确检测到该设备,并且已连接 tty。

但是当我为设备调用 'read' 时,系统调用永远不会终止。奇怪的是,当我使用 MiniCom、CuteCom 甚至 H-Term 访问设备时,它都能正常工作。

我已经尝试过以下问题的答案:

Reading and writing to serial port in C on Linux

How to open, read, and write from serial port in C?

C program to read data from USB device connected to the system

None 他们成功了。

我还尝试用 tcflush 和 tcdrain 刷新 tty。

int dev = open("/dev/ttyACM0", O_RWDR | O_NOCTTY);

// I tried to adapt the device parameters with termios, see above

uint8_t req[] = {0x21, 0x42, 0x00, 0x12}; // the actual request
write(dev, req, 4);

uint8_t resp[12];
read(dev, resp, 8); // does not terminate

我希望得到一个 12 字节长的结果,但只读取块。如果我尝试 O_NONBLOCK/O_NDELAY 选项,读取会因 EAGAIN 错误而终止。

当然,我检查了每个系统调用和库函数的结果值,它们都returned/terminated符合预期。正如我上面提到的,当连接到终端程序时,设备会正常工作,所以它不可能是固件。

我还用 strace 跟踪了 minicom 和 cutecom 做了什么,但它们也只是打开、写入和读取,当然我用 sudo 尝试了一切,所以权限不是问题。

似乎设备从未接受过请求,因此它从未处理过并被阻止。因此,请求的编写方式可能存在问题。您是否尝试设置 port/interface 的速度?

我自己找到了答案:必须清除 termios 结构中的 ICANON 位,c_lflag 字段并且 c_cc 数组中的 VMIN 字段应设置为 1。

进一步的解释可以在这里找到:

https://www.gnu.org/software/libc/manual/html_node/Local-Modes.html#Local-Modes https://www.gnu.org/software/libc/manual/html_node/Mode-Data-Types.html

(请注意,这部纪录片的某些部分有点过时,例如 CCTS_OFLOW Flag 在 Raspbian-Buster 上不存在)