From d44053a99435fb9fc1f408fb3f1629a54c938afc Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 6 Mar 2013 11:26:27 +0100 Subject: [PATCH] Add internal support for enumerating serial ports. For the time being, the serial port enumeration code is of very limited use. It's not used anywhere in the library, and as an internal api it's also not available to applications. It serves mainly as a reference implementation for future use. --- src/serial.h | 4 ++++ src/serial_posix.c | 50 ++++++++++++++++++++++++++++++++++++++++++ src/serial_win32.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) diff --git a/src/serial.h b/src/serial.h index 1f84dcc..0962f4e 100644 --- a/src/serial.h +++ b/src/serial.h @@ -55,6 +55,10 @@ typedef enum serial_line_t { SERIAL_LINE_RNG, // Ring indicator } serial_line_t; +typedef void (*serial_callback_t) (const char *name, void *userdata); + +int serial_enumerate (serial_callback_t callback, void *userdata); + int serial_open (serial_t **device, dc_context_t *context, const char* name); int serial_close (serial_t *device); diff --git a/src/serial_posix.c b/src/serial_posix.c index 801b10c..f4cfa14 100644 --- a/src/serial_posix.c +++ b/src/serial_posix.c @@ -38,6 +38,10 @@ #ifdef HAVE_IOKIT_SERIAL_IOSS_H #include #endif +#include +#include +#include +#include #ifndef TIOCINQ #define TIOCINQ FIONREAD @@ -72,6 +76,52 @@ struct serial_t { unsigned int nbits; }; + +int +serial_enumerate (serial_callback_t callback, void *userdata) +{ + DIR *dp = NULL; + struct dirent *ep = NULL; + const char *dirname = "/dev"; + const char *patterns[] = { +#if defined (__APPLE__) + "tty.*", +#else + "ttyS*", + "ttyUSB*", + "ttyACM*", + "rfcomm*", +#endif + NULL + }; + + dp = opendir (dirname); + if (dp == NULL) { + return -1; + } + + while ((ep = readdir (dp)) != NULL) { + for (size_t i = 0; patterns[i] != NULL; ++i) { + if (fnmatch (patterns[i], ep->d_name, 0) == 0) { + char filename[1024]; + int n = snprintf (filename, sizeof (filename), "%s/%s", dirname, ep->d_name); + if (n >= sizeof (filename)) { + closedir (dp); + return -1; + } + + callback (filename, userdata); + break; + } + } + } + + closedir (dp); + + return 0; +} + + // // Open the serial port. // diff --git a/src/serial_win32.c b/src/serial_win32.c index fa4d00a..62cf486 100644 --- a/src/serial_win32.c +++ b/src/serial_win32.c @@ -47,6 +47,60 @@ struct serial_t { unsigned int nbits; }; +int +serial_enumerate (serial_callback_t callback, void *userdata) +{ + // Open the registry key. + HKEY hKey; + LONG rc = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey); + if (rc != ERROR_SUCCESS) { + if (rc == ERROR_FILE_NOT_FOUND) + return 0; + else + return -1; + } + + // Get the number of values. + DWORD count = 0; + rc = RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL); + if (rc != ERROR_SUCCESS) { + RegCloseKey(hKey); + return -1; + } + + for (DWORD i = 0; i < count; ++i) { + // Get the value name, data and type. + char name[512], data[512]; + DWORD name_len = sizeof (name); + DWORD data_len = sizeof (data); + DWORD type = 0; + rc = RegEnumValue (hKey, i, name, &name_len, NULL, &type, (LPBYTE) data, &data_len); + if (rc != ERROR_SUCCESS) { + RegCloseKey(hKey); + return -1; + } + + // Ignore non-string values. + if (type != REG_SZ) + continue; + + // Prevent a possible buffer overflow. + if (data_len >= sizeof (data)) { + RegCloseKey(hKey); + return -1; + } + + // Null terminate the string. + data[data_len] = 0; + + callback (data, userdata); + } + + RegCloseKey(hKey); + + return 0; +} + // // Open the serial port. //