serialport / serialport-rs

A cross-platform serial port library in Rust. Provides a blocking I/O interface and port enumeration including USB device information.
Other
478 stars 115 forks source link

RaspberryPi: Available ports are not containing the correct info #48

Open teikmeier opened 2 years ago

teikmeier commented 2 years ago

I am working on a Raspberry Pi 4 and trying to use a DMX interface with rust and serialport.

When listing available ports I noticed that the info is not collected properly.

The USB DMX Interface is by Enttec and called DMXIS. It is available through ttyUSB0 and plugged in through the onboard usb ports of the RaspberryPi.

When listing available Ports and printing the info I get the following output:

main.rs

use serialport::{available_ports, SerialPortType};
fn main() {
    let ports = available_ports().expect("No ports found!");
    for port in ports {
        println!("-  {}", port.port_name);
        if let SerialPortType::UsbPort(usb_port_info) = &port.port_type {
            if let Some(product) = &usb_port_info.product {
                println!("   Product: {}", product);
            }
            if let Some(manufacturer) = &usb_port_info.manufacturer {
                println!("   Manufacturer: {}", manufacturer);
            }
            if let Some(serial_number) = &usb_port_info.serial_number {
                println!("   Serial number: {}", serial_number);
            }
        }
        println!("");
    }
}

Output:

> cargo run
   Compiling rustydmx v0.1.0 (/home/pi/rustydmx)
    Finished dev [unoptimized + debuginfo] target(s) in 2.04s
     Running `target/debug/rustydmx`
-  /dev/ttyUSB0
   Product: VL805 USB 3.0 Host Controller
   Manufacturer: VIA Technologies, Inc.
   Serial number: ENVVVCOF

-  /dev/ttyAMA0

However when I run a python script with pyserial I get the correct info:

> python3
>>> from serial.tools import list_ports
>>> port = list(list_ports.comports())
>>> for p in port:
...    print("- " + p.device)
...    print("   " + p.product)
...    print("   " + p.manufacturer)
... 
- /dev/ttyUSB0
   DMXIS
   ENTTEC
- /dev/ttyAMA0

My guess is that the serialport implementation confuses the actual serialport info with the data from the built in usb hub of the RaspberryPi.

One thing I noticed was that the serial_number seemed to be correct at least it matched the number reported when executing udevadm info --query all --name /dev/ttyUSB0 --attribute-walk

Technical data:

> uname -a
Linux raspberrypi 5.15.32-v7l+ #1538 SMP Thu Mar 31 19:39:41 BST 2022 armv7l GNU/Linux

> lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

> dmesg
[13995.091232] usb 1-1.3: new full-speed USB device number 4 using xhci_hcd
[13995.235722] usb 1-1.3: New USB device found, idVendor=0403, idProduct=6001, bcdDevice= 6.00
[13995.235753] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[13995.235773] usb 1-1.3: Product: DMXIS
[13995.235792] usb 1-1.3: Manufacturer: ENTTEC
[13995.235809] usb 1-1.3: SerialNumber: ENVVVCOF
[13995.240163] ftdi_sio 1-1.3:1.0: FTDI USB Serial Device converter detected
[13995.240324] usb 1-1.3: Detected FT232RL
[13995.254635] usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB0

> rustc -V
rustc 1.60.0 (7737e0b5c 2022-04-04)
mlsvrts commented 2 years ago

PySerial reads its port information from sysfs, which I believe will typically agree with udev's ID_VENDOR and ID_MODEL.

However, serialport-rs has prefered *_FROM_DATABASE for about two years, which is not information reported directly from the device.

I believe that udev reads these strings from a binary-blob database that is based on the usb.ids file, so I wonder if Enttec is squatting on an ID that they don't actually own...

However, your dmesg makes me think that FTDI's information should be what's printed -- can you clone the repository and run the list_ports example?

git clone https://github.com/serialport/serialport-rs && cd serialport-rs
cargo run --example list_ports
teikmeier commented 2 years ago

Sure The output looks like this:

     Running `target/debug/examples/list_ports`
Found 2 ports:
  /dev/ttyUSB0
    Type: USB
    VID:0403 PID:6001
     Serial Number: ENVVVCOF
      Manufacturer: VIA Technologies, Inc.
           Product: VL805 USB 3.0 Host Controller
  /dev/ttyAMA0
    Type: Unknown

From the usb.ids file the vid and pid would lead to this: 0403 --> Future Technology Devices International, Ltd 6001 --> FT232 Serial (UART) IC

Gisleburt commented 2 years ago

I might be having a similar problem.

I wrote a pair of programs (both in the same repo) to control leds on the Neo Trinkey, one of which runs on the trinkey and exposes it as a serial device, the other connects using serialport-rs.

This works fine on macos but not on raspios, the devices are not found by serialport-rs (I even added a debug-list option to show all serial devices which returns nothing).

I can see the device in dmesg:

[    3.064356] usb 1-1.3: New USB device found, idVendor=0000, idProduct=0000, bcdDevice= 0.10
[    3.072896] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[    3.080344] usb 1-1.3: Product: Status Lights
[    3.084787] usb 1-1.3: Manufacturer: Gisleburt
[    3.089318] usb 1-1.3: SerialNumber: Gisleburt Neo Trinkey Status Lights

I can also see that raspios detects the correct baud rate on the device

$ stty -F /dev/ttyACM0
speed 9600 baud; line = 0;
-brkint -imaxbel

I've done a lot of google but can't find anything that seems useful.

(Note this also doesn't work on Windows but I only just tried windows tonight and its not a platform I was aiming to support 🤷🏻‍♂️ )

mlsvrts commented 2 years ago

@Gisleburt serialport-rs uses a pretty thin wrapper over libudev for enumeration; can you provide some information about the system you're running on? I can list ports correctly on a CM4 running Ubuntu 20.04 (armv7l):

mlsvrts@ubuntu:~/serialport-rs$ sudo apt list --installed | grep libudev

libudev-dev/focal-updates,now 245.4-4ubuntu3.17 armhf [installed]
libudev1/focal-updates,now 245.4-4ubuntu3.17 armhf [installed,automatic]

mlsvrts@ubuntu:~/serialport-rs$ uname -ar
Linux ubuntu 5.4.0-1060-raspi #68-Ubuntu SMP PREEMPT Tue Apr 26 09:34:31 UTC 2022 armv7l armv7l armv7l GNU/Linux

mlsvrts@ubuntu:~/serialport-rs$ cargo run --example list_ports
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s
     Running `target/debug/examples/list_ports`
Found 3 ports:
  /dev/ttyUSB0
    Type: USB
    VID:067b PID:2303
     Serial Number:
      Manufacturer: Prolific Technology, Inc.
           Product: PL2303 Serial Port
         Interface: 00
  /dev/ttyAMA0
    Type: Unknown
  /dev/ttyS0
    Type: Unknown

mlsvrts@ubuntu:~/serialport-rs$ cargo run --no-default-features --example list_ports
   Compiling serialport v4.2.1-alpha.0 (/home/mlsvrts/serialport-rs)
    Finished dev [unoptimized + debuginfo] target(s) in 5.55s
     Running `target/debug/examples/list_ports`
Found 1 port:
  /sys/class/tty/ttyUSB0
    Type: Unknown
Gisleburt commented 2 years ago

Just to update, thank you for the quick response, and sorry I haven't been able to get back to you properly.

I've run into a problem as I'm running a k3s cluster on the pi's and trying to avoid putting things like the rust toolchain on it. I was using gitlab ci runners running in the cluster to do things like building rust images and applications however right after you sent me the message the helm chart broke, and I haven't figured out how to fix it 🙄

One thing I did wonder is I'm compiling targeting aarch64-unknown-linux-musl and wondered if that might cause problems with libudev but I don't get any errors when running (either in k3s or copying the statically linked executable to the pi directly).

I'll try to update you when my gitlab ci is working again (or I might just buy another Pi specifically to compile on 🤷🏻‍♂️ ), sorry thats not much help.

ZanderBrown commented 2 years ago

Seems like a dup of #17? Anyway, my workaround has been to match on serial number