3

I am trying to recive a array of all connected ports with SerialPort.GetPortNames() in Mono but it returns something like this:

(Mac but it should be the same on Linux)

ApfelBuch:~ janwiesemann$ mono "/Users/janwiesemann/Desktop/ports/ports/bin/Debug/ports.exe"
/dev/tty.Bluetooth-Incoming-Port
/dev/ttyp0
/dev/ttyp1
/dev/ttyp2
/dev/ttyp3
/dev/ttyp4
...
/dev/ttywc
/dev/ttywd
/dev/ttywe
/dev/ttywf

Press any key to continue...

Code used:

string[] ports = SerialPort.GetPortNames();

foreach (string p in ports)
{
    Console.WriteLine (p);
}

so my qestion is how do i find out which ports are acutally connected to my computer?

Jan Wiesemann
  • 455
  • 2
  • 16
  • Is opening (and immediately closing) a SerialPort on each port and catching an exception to determine its availability not an option? – Yarik Nov 07 '16 at 16:56
  • @yarik - not in this case. In my environment I'm seeing over 300 ports listed when no external adapters are plugged in. – RQDQ Nov 08 '16 at 03:51
  • I have the same question. Is it still doesn't work in 2019? – Vlad Feb 14 '19 at 16:26

1 Answers1

2

As you can see in the mono source code, the SerialPort.GetPortNames() method just enumerates the /dev/tty* nodes:

string[] ttys = Directory.GetFiles("/dev/", "tty*");
...
foreach (string dev in ttys) {
    if (linux_style){
        if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM"))
            serial_ports.Add (dev);
    } else {
        if (dev != "/dev/tty" && dev.StartsWith ("/dev/tty") && !dev.StartsWith ("/dev/ttyC"))
            serial_ports.Add (dev);
    }
}

So that's why you're getting all those tty* devices in the output. But it's not so easy to determine which of them actually correspond to a (connected) serial port on your machine.

You can take a look on this answer. They're using an Unix dmesg command there followed by a grep to find out which devices are actually serial ports. They're even trying to figure out which of the serial port is connected on the other side too.

$dmesg | grep ttyS
[    0.872181] 00:06: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A 
[    0.892626] 00:07: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A 
[    0.915797] 0000:01:01.0: ttyS4 at I/O 0x9800 (irq = 19) is a ST16650V2 
[    0.936942] 0000:01:01.1: ttyS5 at I/O 0x9c00 (irq = 18) is a ST16650V2

Alternatively, you could parse the /proc/tty/drivers file, as explained in this answer.

There are a couple of similar questions about it. Perhaps you can find a solution that suits your needs best.

AFAIK there is no simple way to do this in mono directly, you have to go deeper.


UPDATE

The reason why there is only one /dev/ttyUSB0 item in case of a connected FTDI device seems to be pretty obvious.

In the same method, the linux_style flag value is determined by a simple look-up:

if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM")) {
    linux_style = true;
    break;
}

So if there is a ttyUSB* device available, this flag will be set to true. This affects the device enumeration described above which returns a single item.

Community
  • 1
  • 1
dymanoid
  • 14,771
  • 4
  • 36
  • 64