I've just been sniffing around (because of the number of USB-connected devices I've got) and I think I see what's happening at least on older versions: ports which don't quite exist get allocated the serial8250 driver, while ones which really exist are allocated a more recent one
with a pre-6.8 kernel,
all the
/dev/ttySxx ports seem to be associated with the "serial8250" driver, and my code has to iterate over all of them trying to open each
/dev/ttySxx to verify if a given port's hardware exists or not. this check is handled with the fragment of code:
Result:=false;
[...]
FD:=fpOpen('/dev/'+DeviceName, O_RDWR or O_NONBLOCK or O_NOCTTY);
if FD>0 then
try
if fpIOCtl(FD, TIOCGSERIAL, @SS)<>-1 then // note: TIOCGSERIAL is not supported by all USB serial ports, so should only be used on fixed (8250 et al) ports
if SS.typ<>0 then Result:=true;
fpclose(FD)
except end
if a port is
not associated with the "serial8250" driver, then it is
assumed that the hardware is present. ie, removable (USB) serial ports do
not use the "serial8250" driver; fixed serial ports
always use the serial8250" driver. note, i didn't write this code, but merely translated it from what others have variously written, including some C versions. my assumption is that
not trying to open removable/USB serial ports is to save time (i recall reading somewhere that
some bluetooth devices may take a long time to respond). in the past i've found that this code works pretty reliably, but of course that is no guarantee the same approach will continue to work in future!
with the 6.8 kernel, as far as i can tell
all /dev/ttySxx port entries (existent or not) seem to be associated with a driver called "port",
/sys/bus/serial-base/drivers/port.
playing around a bit more with following along the symlinks, i'm now feeling a little more comfortable and can see (roughly) how all the extra back-steps are consumed:
user@user-DH61BE:~$
user@user-DH61BE:/$ cd /
user@user-DH61BE:/$ cd -P sys
user@user-DH61BE:/sys$ cd -P class
user@user-DH61BE:/sys/class$ cd -P tty
user@user-DH61BE:/sys/class/tty$ cd -P ttyS5
user@user-DH61BE:/sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:00.0/0000:02:00.0:0/0000:02:00.0:0.1/tty/ttyS5$ cd -P device
user@user-DH61BE:/sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:00.0/0000:02:00.0:0/0000:02:00.0:0.1$ cd -P ../../../../../../../bus/serial-base/drivers
user@user-DH61BE:/sys/bus/serial-base/drivers$
user@user-DH61BE:/sys/bus/serial-base/drivers$
so it looks like
fpReadLink must follow down the directory tree
one level at a time, stopping before the last step into
driver (which is a final symlink to a file). this gives it a count of how many back-steps are then needed:
/sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:00.0/0000:02:00.0:0/0000:02:00.0:0.1so 7 back-steps, highlighted in red (4) and green (3).
it would be a whole lot easier of
fpReadLink were to return an absolute path, although in the present case we are just interested in the name at the end of the path.
a defensive kernel hacker might be dismissive if you take that sort of liberty :-/
a good point! i just need to figure out if the path
... serial-base/drivers/port can be relied upon in the same way that the name
serial8250 could previously be; just relying upon
port as the identifier feels a tad dangerous!
cheers,
rob :-)