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.
This commit is contained in:
parent
622363dca8
commit
d44053a994
@ -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);
|
||||
|
||||
@ -38,6 +38,10 @@
|
||||
#ifdef HAVE_IOKIT_SERIAL_IOSS_H
|
||||
#include <IOKit/serial/ioss.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <fnmatch.h>
|
||||
|
||||
#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.
|
||||
//
|
||||
|
||||
@ -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.
|
||||
//
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user