From b2ebd56f9cc7d3575eead2893bce1e21f48a2a88 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Sun, 22 Apr 2012 16:46:10 -0700 Subject: [PATCH] Generalized serial port naming syntax to refer to host serial ports by the name 'serN' while continuing to allow the use of specific host device names. Fixed some parsing issues in tmxr_attach_line. --- sim_serial.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++- sim_serial.h | 1 + sim_tmxr.c | 4 +- 3 files changed, 255 insertions(+), 3 deletions(-) diff --git a/sim_serial.c b/sim_serial.c index a75127b8..2f6ad369 100644 --- a/sim_serial.c +++ b/sim_serial.c @@ -45,6 +45,7 @@ sim_read_serial read from a serial port sim_write_serial write to a serial port sim_close_serial close a serial port + sim_show_serial shows the available host serial ports The calling sequences are as follows: @@ -102,13 +103,38 @@ -------------------------------------- The serial port indicated by "port" is closed. + + + int sim_serial_devices (int max, SERIAL_LIST* list) + --------------------------------------------------- + + enumerates the available host serial ports + + + t_stat sim_show_serial (FILE* st) + --------------------------------- + + displays the available host serial ports + */ #include "sim_defs.h" #include "sim_serial.h" +#include +#define SER_DEV_NAME_MAX 256 /* maximum device name size */ +#define SER_DEV_DESC_MAX 256 /* maximum device description size */ +#define SER_MAX_DEVICE 64 /* maximum serial devices */ + +typedef struct serial_list { + char name[SER_DEV_NAME_MAX]; + char desc[SER_DEV_DESC_MAX]; + } SERIAL_LIST; + +static int sim_serial_os_devices (int max, SERIAL_LIST* list); +static SERHANDLE sim_open_os_serial (char *name); /* Generic error message handler. @@ -124,7 +150,149 @@ fprintf (stderr, "Serial: %s fails with error %d\n", routine, error); return; } +/* Used when sorting a list of serial port names */ +static int _serial_name_compare (const void *pa, const void *pb) +{ +SERIAL_LIST *a = (SERIAL_LIST *)pa; +SERIAL_LIST *b = (SERIAL_LIST *)pb; +return strcmp(a->name, b->name); +} + +t_stat sim_show_serial (FILE* st) +{ +SERIAL_LIST list[SER_MAX_DEVICE]; +int number = sim_serial_os_devices(SER_MAX_DEVICE, list); + +fprintf(st, "Serial devices:\n"); +if (number == -1) + fprintf(st, " serial support not available in simulator\n"); +else +if (number == 0) + fprintf(st, " no serial devices are available\n"); +else { + size_t min, len; + int i; + for (i=0, min=0; i min) + min = len; + for (i=0; i s2) + return 1; + if (s1 == 0) + return 0; +} +return 0; +} + +static char* sim_serial_getname_byname(char* name, char* temp) +{ +SERIAL_LIST list[SER_MAX_DEVICE]; +int count = sim_serial_os_devices(SER_MAX_DEVICE, list); +size_t n; +int i, found; + +found = 0; +n = strlen(name); +for (i=0; i 0)) + if (ports < max) + ++ports; + else + break; + /* Besure to clear the working entry before trying again */ + memset(list[ports].name, 0, sizeof(list[ports].name)); + memset(list[ports].desc, 0, sizeof(list[ports].desc)); + dwValueNameSize = sizeof(list[ports].desc); + dwDataSize = sizeof(list[ports].name); + ++dwIndex; + } + RegCloseKey(hSERIALCOMM); + } +if (ports) /* Order the list returned alphabetically by the port name */ + qsort (list, ports, sizeof(list[0]), _serial_name_compare); +return ports; +} + /* Open a serial port. The serial port designated by "name" is opened, and the handle to the port is @@ -157,7 +368,7 @@ return; interest to a DCB retrieved from a call to "GetCommState". */ -SERHANDLE sim_open_serial (char *name) +SERHANDLE sim_open_os_serial (char *name) { SERHANDLE port; DCB dcb; @@ -421,6 +632,44 @@ return; #elif defined (__unix__) +/* Enumerate the available serial ports. + + The serial port names generated by attempting to open /dev/ttyS0 thru + /dev/ttyS53 and /dev/ttyUSB0 thru /dev/ttyUSB0. Ones we can open and + are ttys (as determined by isatty()) are added to the list. The list + is sorted alphabetically by device name. + +*/ + +static int sim_serial_os_devices (int max, SERIAL_LIST* list) +{ +int i; +int port; +int ports = 0; + +memset(list, 0, max*sizeof(*list)); +for (i=0; (ports < max) && (i < 64); ++i) { + sprintf (list[ports].name, "/dev/ttyS%d", i); + port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ + if (port != -1) { /* open OK? */ + if (isatty (port)) /* is device a TTY? */ + ++ports; + close (port); + } + } +for (i=0; (ports < max) && (i < 64); ++i) { + sprintf (list[ports].name, "/dev/ttyUSB%d", i); + port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ + if (port != -1) { /* open OK? */ + if (isatty (port)) /* is device a TTY? */ + ++ports; + close (port); + } + } +if (ports) /* Order the list returned alphabetically by the port name */ + qsort (list, ports, sizeof(list[0]), _serial_name_compare); +return ports; +} /* Open a serial port. @@ -442,7 +691,7 @@ return; reading. */ -SERHANDLE sim_open_serial (char *name) +SERHANDLE sim_open_os_serial (char *name) { static const tcflag_t i_clear = IGNBRK | /* ignore BREAK */ BRKINT | /* signal on BREAK */ diff --git a/sim_serial.h b/sim_serial.h index 64ffdeb1..e6a217eb 100644 --- a/sim_serial.h +++ b/sim_serial.h @@ -95,5 +95,6 @@ extern t_bool sim_control_serial (SERHANDLE port, t_bool connect); extern int32 sim_read_serial (SERHANDLE port, char *buffer, int32 count, char *brk); extern int32 sim_write_serial (SERHANDLE port, char *buffer, int32 count); extern void sim_close_serial (SERHANDLE port); +extern t_stat sim_show_serial (FILE* st); #endif diff --git a/sim_tmxr.c b/sim_tmxr.c index d99d1ed7..3112c73b 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -1300,6 +1300,8 @@ char portname [1024]; t_bool arg_error = FALSE; if (val) { /* explicit line? */ + if (cptr == NULL) /* arguments supplied? */ + return SCPE_ARG; /* report bad argument */ uptr = NULL; /* indicate to get routine */ tptr = strchr (cptr, (char) val); /* search for separator */ @@ -1320,7 +1322,7 @@ if (lp->conn) /* line connected via Te if (val) /* named line form? */ cptr = tptr + 1; /* point at port name */ -if (cptr == NULL) /* port name missing? */ +if ((cptr == NULL) || (!*cptr)) /* port name missing? */ return SCPE_ARG; /* report it */ pptr = get_glyph_nc (cptr, portname, ';'); /* separate port name from optional params */