Fazecast / jSerialComm

Platform-independent serial port access for Java
GNU Lesser General Public License v3.0
1.31k stars 278 forks source link

Linux Enhancement request: Include symlinks in GetCommPorts return #567

Open newHeiko opened 1 month ago

newHeiko commented 1 month ago

Hello and thanks for this piece of software!

We recently switched JMRI: https://jmri.org over from PureJavaComm to jSerialComm to future-proof it.

One issue we are just now running into: Since Linux re-enumerates USB-Serial-Adapters depending on the order of plugging them in, some of our Linux users use udev-generated symlinks to tell multiple different USB->Serial adapters apart. For example, what could today be:

/dev/PR3Adapter -> /dev/ttyUSB0 /dev/NCEAdapter -> /dev/ttyUSB1 /dev/LokProgrammer -> /dev/ttyACM4

might tomorrow or after a couple of unplugging/replugging cycles look like:

/dev/PR3Adapter -> /dev/ttyUSB1 /dev/NCEAdapter -> /dev/ttyUSB0 /dev/LokProgrammer -> /dev/ttyACM2

We'd love to have the return value of GetCommPorts include those symlinks. Would you accept a PR that adds to https://github.com/Fazecast/jSerialComm/blob/a8a307deed68bca2dda3048c1ecc5481eb5783fb/src/main/c/Posix/PosixHelperFunctions.c#L649 another iteration through /dev, looking for symlinks to ports already in the vector and adding the symlinks to the comPorts vector? (Would that even work if they refer to the same physical port but show up twice in the result?)

If not, I'll give our port selector another deep look.

Thanks, Heiko

danielb987 commented 1 month ago

I'm not sure I understand the code in searchForComPorts() but it looks to me that what's needed is:

if (isPtyDevice(fileName))
    pushBack(comPorts, fileName, "PTY Device", "Pseudo-Terminal Device", "0-0", "Unknown", "Unknown", -1, -1);
else if (isTtyDevice(fileName))    // These two lines are added to handle symlinks by udev.
    pushBack(comPorts, fileName, "TTY Device", "Pseudo-Terminal Device", "0-0", "Unknown", "Unknown", -1, -1);
else if (isBluetoothDevice(fileName))
    pushBack(comPorts, fileName, "Bluetooth Device", "Bluetooth Device", "0-0", "Unknown", "Unknown", -1, -1);

at lines 665-668 and that the method isTtyDevice() is added.

newHeiko commented 1 month ago

That would be an option, certainly.

I guess it would be cleaner to add another loop, so it could just check any symlink in /dev/ if it links against a file already in the comPorts-Vector.

And probably copy the properties of the device it links to, instead of just filling it with "Unknown", "Unknown".

Heiko

edit: But let's wait for comments from the maintainer(s) of this library before discussing implementation details...