Jan18101997 Jan18101997 - 22 days ago 8
C# Question

Mono SerialPort.GetPortNames() actually connected?

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?

Answer

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.

Comments