为啥pyserial填充USB数据包?

Posted

技术标签:

【中文标题】为啥pyserial填充USB数据包?【英文标题】:Why is pyserial padding USB Packets?为什么pyserial填充USB数据包? 【发布时间】:2021-03-04 16:56:26 【问题描述】:

我正在尝试通过 USB 将 Newport AGILIS AG-UC8 控制器连接到我的 Linux。 在内部,这个控制器有一个 FT232R usb-to-serial 芯片,它应该接受简单的文本命令,例如 "VE\r\n" 来打印版本。

使用提供的 Windows 驱动程序和软件时,这工作正常,但在 Linux 上(使用 pyserial 和其他测试),芯片没有响应。基本上我用 Windows 设备管理器显示的值初始化设备,然后发送命令。

ser = serial.Serial(port='/dev/ttyUSB0', baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)
ser.write("VE\r\n")

我用wireshark USB捕获做了一些调试:

Windows 数据包(工作,来自提供的软件):

0000   1b 00 20 9a 40 55 8a ad ff ff 00 00 00 00 09 00   .. .@U..........
0010   00 01 00 03 00 02 03 04 00 00 00 56 45 0d 0a      ...........VE..

Linux 数据包(不工作,来自 pyserial):

0000   80 dd 35 82 e5 99 ff ff 53 03 02 08 02 00 2d 00   ..5.....S.....-.
0010   b6 08 41 60 00 00 00 00 3a 6f 00 00 8d ff ff ff   ..A`....:o......
0020   04 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00   ................
0030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0040   56 45 0d 0a                                       VE..

如您所见,windows 上的数据包要小得多,并且不包含填充零。这些零紧跟在数据长度字段 (04) 之后,所以我想知道它们是否会给控制器带来问题。

有没有办法在没有零填充的情况下发送数据?最好在 pyserial 中,但现在我对任何可以让我与我的设备对话的解决方案都很满意。

【问题讨论】:

尝试写“VE”而不写“\r\n”,这可能会导致没有响应。如果我是说控制器语言,我不会期待这些,除非我在文档中特别要求它们。浪费了两个字节。 @vhoang windows 数据包结束于 56 45 0d 0a 这是 \r\n 我认为控制器期望它们 我明白了,我找到了文档,它确实将术语字符列为 CR/LF。我注意到的唯一可能导致某些问题的另一件事是波特率预计为 921600。您不应该能够在 9600 处读取正确的响应,如果它在 Windows 中工作,这很奇怪。 也许我还是应该试试 921600 的波特率,但我的产品手册实际上指定了 9600... 【参考方案1】:

回答您的问题,但不一定解决您的问题:那些额外的零是由于嗅探器捕获内核和 libusb 之间的流量。这也是您的捕获在不同环境之间看起来不同的原因。

具体来说,它们是填充到位于 urb 和数据长度之后的 pcap_usb_setup 结构中的值。没有特别的方法或理由可以尝试消除它们。

/*
 * Header prepended by linux kernel to each event.
 * Appears at the front of each packet in DLT_USB_LINUX captures.
 */
typedef struct _usb_header 
    uint64_t id;
    uint8_t event_type;
    uint8_t transfer_type;
    uint8_t endpoint_number;
    uint8_t device_address;
    uint16_t bus_id;
    char setup_flag;/*if !=0 the urb setup header is not present*/
    char data_flag; /*if !=0 no urb data is present*/
    int64_t ts_sec;
    int32_t ts_usec;
    int32_t status;
    uint32_t urb_len;
    uint32_t data_len; /* amount of urb data really present in this event*/
    pcap_usb_setup setup;
 pcap_usb_header;
/*
 * USB setup header as defined in USB specification.
 * Appears at the front of each Control S-type packet in DLT_USB captures.
 */
typedef struct _usb_setup 
    uint8_t bmRequestType;
    uint8_t bRequest;
    uint16_t wValue;
    uint16_t wIndex;
    uint16_t wLength;
 pcap_usb_setup;

【讨论】:

以上是关于为啥pyserial填充USB数据包?的主要内容,如果未能解决你的问题,请参考以下文章

GNU/Linux - Python3 - PySerial:如何通过 USB 连接发送数据?

使用 pyserial 识别给定 USB VID 和 PID 的 USB 到串行端口

PySerial 丢失数据

对带有 USB 全速半双工通话优先级的 PySerial 感到困惑

转:Python通过pyserial控制串口操作

电脑上用wireshark软件为啥抓不到带VLAN TAG的数据包,是软件问题还是网卡问题