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 */