refactor comport_ports() and comport_devices() to common comport_enum()

This commit is contained in:
Antoine Rousseau 2024-10-07 18:33:25 +02:00
parent 328a3ec553
commit 8b170f3d35

164
comport.c
View file

@ -79,7 +79,7 @@ typedef struct comport
/* device specifications */ /* device specifications */
t_symbol *serial_device; t_symbol *serial_device;
const char* pretty_name; const char* pretty_name;
char serial_device_prefix[MAXPDSTRING];/* the device name without the number */ const char *serial_device_prefix;/* the device name without the number */
short comport; /* holds the comport # */ short comport; /* holds the comport # */
/* device configuration */ /* device configuration */
@ -332,7 +332,7 @@ static void comport_output_rtscts(t_comport *x);
static void comport_output_xonxoff(t_comport *x); static void comport_output_xonxoff(t_comport *x);
static void comport_output_hupcl(t_comport *x); static void comport_output_hupcl(t_comport *x);
static void comport_output_rxerrors(t_comport *x); static void comport_output_rxerrors(t_comport *x);
static void comport_enum(t_comport *x); static void comport_enum(t_comport *x, t_bool to_console);
static void comport_info(t_comport *x); static void comport_info(t_comport *x);
static void comport_devices(t_comport *x); static void comport_devices(t_comport *x);
static void comport_ports(t_comport *x); static void comport_ports(t_comport *x);
@ -346,6 +346,23 @@ void comport_setup(void);
/* ------------ sys dependent serial setup helpers ---------------- */ /* ------------ sys dependent serial setup helpers ---------------- */
#ifdef _WIN32
/* According to http://msdn2.microsoft.com/en-us/library/aa363858.aspx To
specify a COM port number greater than 9, use the following syntax:
"\\\\.\\COM10". This syntax works for all port numbers and hardware that
allows COM port numbers to be specified. */
static const char SERIAL_DEVICE_PREFIX[] = "\\\\.\\COM";
//static const char USB_DEVICE_PREFIX[] = "\\\\.\\COM";
/* for UNIX, this is a glob pattern for matching devices */
#elif defined __APPLE__
static const char SERIAL_DEVICE_PREFIX[] = "/dev/tty.*";
#elif defined __linux__
/* serial: ttyS? USB-serial: ttyUSB? USB-CDC: ttyACM? */
static const char SERIAL_DEVICE_PREFIX[] = "/dev/tty[ASU]*";
#elif defined IRIX
static const char SERIAL_DEVICE_PREFIX[] = "/dev/ttyd*";
#endif
/* --------------------- NT ------------------------------------ */ /* --------------------- NT ------------------------------------ */
@ -1360,21 +1377,7 @@ static void *comport_new(t_symbol *s, int argc, t_atom *argv)
int ibaud = 9600; int ibaud = 9600;
(void)s; /* squelch unused-parameter warning */ (void)s; /* squelch unused-parameter warning */
#ifdef _WIN32 serial_device_prefix = SERIAL_DEVICE_PREFIX;
/* According to http://msdn2.microsoft.com/en-us/library/aa363858.aspx To
specify a COM port number greater than 9, use the following syntax:
"\\\\.\\COM10". This syntax works for all port numbers and hardware that
allows COM port numbers to be specified. */
serial_device_prefix = "\\\\.\\COM";
/* for UNIX, this is a glob pattern for matching devices */
#elif defined __APPLE__
serial_device_prefix = "/dev/tty.*";
#elif defined __linux__
/* serial: ttyS? USB-serial: ttyUSB? USB-CDC: ttyACM? */
serial_device_prefix = "/dev/tty[ASU]*";
#elif defined IRIX
serial_device_prefix = "/dev/ttyd*";
#endif
if(argc > 0) { if(argc > 0) {
if (argv->a_type == A_FLOAT) if (argv->a_type == A_FLOAT)
@ -1387,12 +1390,8 @@ allows COM port numbers to be specified. */
/* Open the Comport for RD and WR and get a handle */ /* Open the Comport for RD and WR and get a handle */
/* this line should use a real serial device */ /* this line should use a real serial device */
#ifdef _WIN32
strncpy_s(test.serial_device_prefix, strlen(serial_device_prefix) + 1, serial_device_prefix, strlen(serial_device_prefix) + 1); test.serial_device_prefix = serial_device_prefix;
#else
strncpy(test.serial_device_prefix, serial_device_prefix, MAXPDSTRING-1);
test.serial_device_prefix[MAXPDSTRING-1] = 0;
#endif
test.baud = ibaud; test.baud = ibaud;
test.data_bits = 8; /* default 8 data bits */ test.data_bits = 8; /* default 8 data bits */
test.parity_bit = 0;/* default no parity bit */ test.parity_bit = 0;/* default no parity bit */
@ -1417,11 +1416,8 @@ allows COM port numbers to be specified. */
x = (t_comport *)pd_new(comport_class); x = (t_comport *)pd_new(comport_class);
x->comport = test.comport;/* com_num */ x->comport = test.comport;/* com_num */
#ifdef _WIN32 x->serial_device_prefix = serial_device_prefix;
strncpy_s(x->serial_device_prefix, strlen(serial_device_prefix) + 1, serial_device_prefix, strlen(serial_device_prefix) + 1);
#else
strncpy(x->serial_device_prefix, serial_device_prefix, MAXPDSTRING);
#endif
x->serial_device = test.serial_device; /* we need this so 'help' doesn't crash */ x->serial_device = test.serial_device; /* we need this so 'help' doesn't crash */
x->baud = test.baud; x->baud = test.baud;
@ -1704,12 +1700,13 @@ static void comport_print(t_comport *x, t_symbol *s, int argc, t_atom *argv)
} }
} }
static void comport_enum(t_comport *x) static void comport_enum(t_comport *x, t_bool to_console)
{ {
unsigned int i;
t_atom output_atom[2];
#ifdef _WIN32 #ifdef _WIN32
HANDLE fd; HANDLE fd;
char device_name[10]; char device_name[10];
unsigned int i;
DWORD dw; DWORD dw;
for(i = 1; i < COMPORT_MAX; i++) for(i = 1; i < COMPORT_MAX; i++)
{ {
@ -1730,11 +1727,20 @@ static void comport_enum(t_comport *x)
dw = GetLastError(); dw = GetLastError();
else else
CloseHandle(fd); CloseHandle(fd);
if (dw == 0)post("\t%d - COM%d (free)", i, i); if(to_console)
else if (dw == ERROR_ACCESS_DENIED)pd_error(x, "\t%d - COM%d (in use)", i, i); {
if (dw == 0) post("\t%d - COM%d (free)", i, i);
else if (dw == ERROR_ACCESS_DENIED) pd_error(x, "\t%d - COM%d (in use)", i, i);
} else {
if ((dw == 0)||(dw == ERROR_ACCESS_DENIED))
{ /* output index and name as a list */
SETFLOAT(&output_atom[0], i);
SETSYMBOL(&output_atom[1], gensym(&device_name[4]));/* strip the slashes and dot */
outlet_anything( x->x_status_outlet, gensym("ports"), 2, output_atom);
}
}
} }
#else #else
unsigned int i;
glob_t glob_buffer; glob_t glob_buffer;
int fd; int fd;
struct termios test; struct termios test;
@ -1762,8 +1768,16 @@ static void comport_enum(t_comport *x)
if((fd = open(glob_buffer.gl_pathv[i], OPENPARAMS)) != INVALID_HANDLE_VALUE) if((fd = open(glob_buffer.gl_pathv[i], OPENPARAMS)) != INVALID_HANDLE_VALUE)
{ {
/* now see if it has attributes */ /* now see if it has attributes */
if ((tcgetattr(fd, &test)) != -1) if ((tcgetattr(fd, &test)) != -1) {
if(to_console)
{
post("\t%d\t%s", i, glob_buffer.gl_pathv[i]);// this one really exists post("\t%d\t%s", i, glob_buffer.gl_pathv[i]);// this one really exists
} else {
SETFLOAT(&output_atom[0], i);
SETSYMBOL(&output_atom[1], gensym(glob_buffer.gl_pathv[i]));
outlet_anything( x->x_status_outlet, gensym("ports"), 2, output_atom);
}
}
close (fd); close (fd);
} }
} }
@ -1771,87 +1785,10 @@ static void comport_enum(t_comport *x)
} }
static void comport_ports(t_comport *x) static void comport_ports(t_comport *x)
{ /* the same as comport_enum except outputs list of available ports on status outlet */
unsigned int i;
t_atom output_atom[2];
#ifdef _WIN32
HANDLE fd;
char device_name[10];
DWORD dw;
for(i = 1; i < COMPORT_MAX; i++)
{
#ifdef _MSC_VER
sprintf_s(device_name, 10, "%s%d", x->serial_device_prefix, i);
#else
sprintf(device_name, "%s%d", x->serial_device_prefix, i);
#endif
fd = CreateFileA( device_name,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
dw = 0L;
if(fd == INVALID_HANDLE_VALUE)
dw = GetLastError();
else
CloseHandle(fd);
if ((dw == 0)||(dw == ERROR_ACCESS_DENIED))
{ /* output index and name as a list */
SETFLOAT(&output_atom[0], i);
SETSYMBOL(&output_atom[1], gensym(&device_name[4]));/* strip the slashes and dot */
outlet_anything( x->x_status_outlet, gensym("ports"), 2, output_atom);
}
}
#else
glob_t glob_buffer;
int fd;
struct termios test;
/* first look for registered devices in the filesystem */
switch( glob( x->serial_device_prefix, 0, NULL, &glob_buffer ) )
{
case GLOB_NOSPACE:
pd_error(x,"[comport] out of memory for \"%s\"",x->serial_device_prefix);
break;
# ifdef GLOB_ABORTED
case GLOB_ABORTED:
pd_error(x,"[comport] aborted \"%s\"",x->serial_device_prefix);
break;
# endif /* GLOB_ABORTED */
# ifdef GLOB_NOMATCH
case GLOB_NOMATCH:
pd_error(x,"[comport] no serial devices found for \"%s\"",x->serial_device_prefix);
break;
# endif /* GLOB_NOMATCH */
}
for(i = 0; (i < glob_buffer.gl_pathc) && (i < COMPORT_MAX); i++)
{
/* now try to open the device */
if((fd = open(glob_buffer.gl_pathv[i], OPENPARAMS)) != INVALID_HANDLE_VALUE)
{
/* now see if it has attributes */
if ((tcgetattr(fd, &test)) != -1)
{ /* output index and name as a list */
SETFLOAT(&output_atom[0], i);
SETSYMBOL(&output_atom[1], gensym(glob_buffer.gl_pathv[i]));
outlet_anything( x->x_status_outlet, gensym("ports"), 2, output_atom);
}
close (fd);
}
}
#endif /* _WIN32 */
}
static void comport_output_print(t_comport *x)
{ {
post("[comport]: available serial ports:"); comport_enum(x, 0);
comport_enum(x);
} }
static void comport_output_status(t_comport *x, t_symbol *selector, t_float output_value) static void comport_output_status(t_comport *x, t_symbol *selector, t_float output_value)
{ {
t_atom *output_atom = getbytes(sizeof(t_atom)); t_atom *output_atom = getbytes(sizeof(t_atom));
@ -1929,7 +1866,8 @@ static void comport_output_open_status(t_comport *x)
static void comport_devices(t_comport *x) static void comport_devices(t_comport *x)
{ {
comport_output_print(x); post("[comport]: available serial ports:");
comport_enum(x, 1);
} }
static void comport_info(t_comport *x) static void comport_info(t_comport *x)