Closed JaCzekanski closed 3 years ago
Scanning /dev
works pretty good :)
int scan_ports()
{
struct dirent *ent;
char ftmp[PATH_MAX];
struct stat st;
DIR *dir = NULL;
char *link, *driver, *desc, *name;
nbports = 0;
#ifdef __APPLE__
dir = opendir("/dev");
if (!dir)
goto end;
while (nbports < MAXPORTS) {
ent = readdir(dir);
if (!ent)
break;
if (in_list(exclude_list, ent->d_name))
continue;
if (restrict_list && !in_list(restrict_list, ent->d_name))
continue;
if (strstr(ent->d_name, "cu.") != ent->d_name)
continue;
snprintf(ftmp, sizeof(ftmp), "/dev/%s", ent->d_name);
if (stat(ftmp, &st) == 0) {
serial_ports[nbports].name = strdup(ent->d_name);
serial_ports[nbports].driver = NULL;
serial_ports[nbports].desc = NULL;
serial_ports[nbports].ctime = st.st_ctime;
nbports++;
continue;
}
}
#else
$ ./bin/bt -n
2 ports found, waiting for a new one...
port | age (sec) | device | driver | description
------+------------+------------+------------------+----------------------
2 | 0 | cu.usbserial-0001 | |
Trying port cu.usbserial-0001... Connected to cu.usbserial-0001 at 115200 bps.
Escape character is 'Ctrl-]'. Use escape followed by '?' for help.
Hello world!
BootTerm supports several single-character commands after the escape character:
H h ? display this help
Q q . quit
P p show port status
D d flip DTR pin
R r flip RTS pin
F f flip both DTR and RTS pins
B b send break
C c enable / disable capture
Enter the escape character again after this menu to use these commands.
Port name: cu.usbserial-0001 Speed: 115200 bps Pins: dtr RTS cts dsr cd ri
Port name: cu.usbserial-0001 Speed: 115200 bps Pins: dtr rts cts dsr cd ri
Port name: cu.usbserial-0001 Speed: 115200 bps Pins: DTR RTS cts dsr cd ri
Sent break
Not sure whether you're okay with #ifdef
ing parts of the code or would you rather have separate functions (scan_ports_osx, scan_ports_unix, etc) or even implementations in a separate .c file (selected in Makefile)
Perfect! I was indeed thinking about using ifdefs for the scan, as I'm having some experimental code working on freebsd that will also have to use ifdefs. Thus my idea was to have an ifdef linux
for the current version, an ifdef freebsd
for the second one once done, and an else
using a generic scan of /dev/. Then as we improve our knowledge of certain OSes, we can improve the situation for them while still keeping the fallback like you did above. We could then even add other ifdefs around the test for the device name.
However, please put the ifdefs around the full function. It will be easier regarding the local variables and generally more readable.
For macOS I found some resources here but I don't have such a machine and the discovery process looks fairly complex: https://developer.apple.com/documentation/iokit/1514494-ioservicegetmatchingservices?language=objc http://mirror.informatimago.com/next/developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html
Thus I think that macOS will stay on /dev for a while :-)
Thanks!
For macOS I found some resources here but I don't have such a machine and the discovery process looks fairly complex: developer.apple.com/documentation/iokit/1514494-ioservicegetmatchingservices?language=objc http://mirror.informatimago.com/next/developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html
This might work, but I doubt it's worth the effort - macOS APIs often require you to write Obj-C (not sure if it also applies to kernel APIs) and in this case, we don't get any more information besides what's available by scanning /dev
.
there's also a cmd line tool that can probe device information:
$ ioreg -l -r -c IOSerialBSDClient
+-o IOSerialBSDClient <class IOSerialBSDClient, id 0x10003b90a, registered, matched, active, busy 0 (0 ms), retain 5>
{
"IOClass" = "IOSerialBSDClient"
"CFBundleIdentifier" = "com.apple.iokit.IOSerialFamily"
"IOProviderClass" = "IOSerialStreamSync"
"IOTTYBaseName" = "usbserial-"
"IOSerialBSDClientType" = "IOSerialStream"
"IOProbeScore" = 1000
"IOResourceMatch" = "IOBSD"
"IOCalloutDevice" = "/dev/cu.usbserial-0001"
"IOMatchCategory" = "IODefaultMatchCategory"
"IOTTYDevice" = "usbserial-0001"
"IODialinDevice" = "/dev/tty.usbserial-0001"
"CFBundleIdentifierKernel" = "com.apple.iokit.IOSerialFamily"
"IOTTYSuffix" = "0001"
}
+-o IOSerialBSDClient <class IOSerialBSDClient, id 0x1000004e7, registered, matched, active, busy 0 (0 ms), retain 5>
{
"IOClass" = "IOSerialBSDClient"
"CFBundleIdentifier" = "com.apple.iokit.IOSerialFamily"
"IOProviderClass" = "IOSerialStreamSync"
"IOTTYBaseName" = "Bluetooth-Incoming-Port"
"IOSerialBSDClientType" = "IORS232SerialStream"
"IOProbeScore" = 1000
"IOResourceMatch" = "IOBSD"
"IOCalloutDevice" = "/dev/cu.Bluetooth-Incoming-Port"
"IOMatchCategory" = "IODefaultMatchCategory"
"IOTTYDevice" = "Bluetooth-Incoming-Port"
"IODialinDevice" = "/dev/tty.Bluetooth-Incoming-Port"
"CFBundleIdentifierKernel" = "com.apple.iokit.IOSerialFamily"
"IOTTYSuffix" = ""
}
+-o IOSerialBSDClient <class IOSerialBSDClient, id 0x1000004ea, registered, matched, active, busy 0 (0 ms), retain 5>
{
"IOClass" = "IOSerialBSDClient"
"CFBundleIdentifier" = "com.apple.iokit.IOSerialFamily"
"IOProviderClass" = "IOSerialStreamSync"
"IOTTYBaseName" = "Khronos-SPPDev"
"IOSerialBSDClientType" = "IORS232SerialStream"
"IOProbeScore" = 1000
"IOResourceMatch" = "IOBSD"
"IOCalloutDevice" = "/dev/cu.Khronos-SPPDev"
"IOMatchCategory" = "IODefaultMatchCategory"
"IOTTYDevice" = "Khronos-SPPDev"
"IODialinDevice" = "/dev/tty.Khronos-SPPDev"
"CFBundleIdentifierKernel" = "com.apple.iokit.IOSerialFamily"
"IOTTYSuffix" = ""
}
Perfect! I was indeed thinking about using ifdefs for the scan, as I'm having some experimental code working on freebsd that will also have to use ifdefs.
Do you want me to include fixes in the code and submit them as a Pull request?
Thanks for checking. The interesting part there would be the base name but it's already used in the tty device name so it's explicit enough I think.
Feel free to send your proposed changes!
By the way, I suggest that you place the whole function in a #else
block and that only the tests on "cu." is tested for macos. Ah and one thing, please use strncmp() instead of strstr(), it's a bit cleaner :-)
Merged your patches, closing now. Feel free to reopen if I broke anything!
(continuation of #2)
Sadly, no :(
macOS doesn't have "Serial" hardware type in System information. Only USB devices can be listed:
but that still doesn't give us any direct info about Serial without doing VID/PID lookups.
Diff of
/dev
before and after connecting CP2102.(Weird that it is visible as two separate devices, maybe it's something related to my system setup/drivers) [edit] That was a driver issue - I had installed both Apple and Silabs kexts, uninstalling the later fixed the issue.
and here's for the FTDI
Looks like the Arduino IDE went the easy way and just lists all
^cu\.
devices.