summaryrefslogtreecommitdiff
path: root/mbglib/common/mbgserio.c
diff options
context:
space:
mode:
Diffstat (limited to 'mbglib/common/mbgserio.c')
-rw-r--r--mbglib/common/mbgserio.c929
1 files changed, 708 insertions, 221 deletions
diff --git a/mbglib/common/mbgserio.c b/mbglib/common/mbgserio.c
index 23005b7..ccb8130 100644
--- a/mbglib/common/mbgserio.c
+++ b/mbglib/common/mbgserio.c
@@ -1,7 +1,7 @@
/**************************************************************************
*
- * $Id: mbgserio.c 1.3 2009/09/01 10:49:30 martin REL_M $
+ * $Id: mbgserio.c 1.6.1.17 2015/07/22 16:02:52 martin TEST $
*
* Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
*
@@ -10,6 +10,51 @@
*
* -----------------------------------------------------------------------
* $Log: mbgserio.c $
+ * Revision 1.6.1.17 2015/07/22 16:02:52 martin
+ * Cleanup.
+ * Removed trailing whitespace.
+ * Revision 1.6.1.16 2014/05/27 11:26:24 martin
+ * Revision 1.6.1.15 2014/05/09 11:40:41 marvin
+ * Fixed port_str_list if current port already opened.
+ * Revision 1.6.1.14 2014/03/27 11:48:47Z martin
+ * Revision 1.6.1.13 2014/03/18 10:37:52 martin
+ * Revision 1.6.1.12 2014/03/14 15:41:58Z martin
+ * Revision 1.6.1.11 2014/03/13 14:31:44Z martin
+ * Fixed compiler warnings related to select() call.
+ * Revision 1.6.1.10 2014/03/11 14:08:57Z martin
+ * Revision 1.6.1.9 2014/03/07 13:20:55Z martin
+ * Tmp. saved changes.
+ * Revision 1.6.1.8 2014/03/06 15:25:19 martin
+ * Revision 1.6.1.7 2014/03/04 12:08:12 martin
+ * Revision 1.6.1.6 2014/03/04 11:56:33Z martin
+ * Revision 1.6.1.5 2014/01/31 08:49:00Z marvin
+ * Replaced MBG_ERR_CONNECT_DEF by MBG_ERR_OPEN.
+ * Revision 1.6.1.4 2014/01/08 17:19:41Z martin
+ * MBG_TGT_POSIX
+ * New libusb
+ * Revision 1.6.1.3 2014/01/07 17:00:18 martin
+ * Use common Meinberg error codes.
+ * Revision 1.6.1.2 2013/12/16 10:11:34 marvin
+ * Changed mbgerror return code.
+ * Revision 1.6.1.1 2013/12/13 13:08:19Z marvin
+ * Changed error codes. Get error codes from mbgerror.h
+ * Revision 1.6 2013/04/18 13:50:58Z udo
+ * use O_CLOEXEC on open serial port if defined
+ * Revision 1.5 2013/02/01 16:06:33 martin
+ * Always use mbgserio_read/write rather than the macros.
+ * Got rid of _mbg_open/close/read/write() macros.
+ * Check return code of tcgetattr() when opening port under Linux.
+ * Set up DCB under Windows when opening the port,
+ * not when setting parameters.
+ * Fixed setting up COM port list under Windows.
+ * Flush output on close.
+ * Debug code to test flush under Windows (doesn't seem
+ * to work properly).
+ * New code trying different ways to detect existing ports
+ * reliably under Linux.
+ * Syntax workaround which is required until this module becomes a DLL.
+ * Revision 1.4 2011/07/29 10:12:15 martin
+ * Allow baud rates 115200 and 230400 under Linux, if supported by the OS version.
* Revision 1.3 2009/09/01 10:49:30 martin
* Cleanup for CVI.
* Use new portable timeout functions from mbg_tmo.h.
@@ -28,21 +73,23 @@
#define _MBGSERIO
#include <mbgserio.h>
-
- //##++ The following lines are required
- // until mbgserio becomes a DLL:
- #undef _MBG_API_ATTR
- #define _MBG_API_ATTR
-
#undef _MBGSERIO
#include <stdio.h>
#include <ctype.h>
#include <time.h>
+#include <mbgerror.h>
-#if defined( MBG_TGT_UNIX )
- #include <unistd.h>
+#if defined( MBG_TGT_POSIX )
#include <fcntl.h>
+ #include <dirent.h>
+ #include <errno.h>
+#endif
+
+
+
+#if defined( MBG_TGT_POSIX )
+ static const char dev_dir[] = "/dev";
#endif
@@ -68,8 +115,8 @@ int v24open( char *portname, int mode );
* port could not be opened.
*/
-#define O_DIRECT 0x0100 /* Schnittstelle fuer direkten Hardware-Zugriff oeffnen */
-#define O_HIGHPRIO 0x2000 /* Schnittstelle mit hoher Prioritaet oeffnen (fastopen) */
+#define O_DIRECT 0x0100 /* open port with direct access to the hardware */
+#define O_HIGHPRIO 0x2000 /* open port with high priority (fastopen) */
#define OPEN_MODE ( O_DIRECT | O_HIGHPRIO )
@@ -106,14 +153,156 @@ int v24close( int port );
+#if defined( MBG_TGT_WIN32 )
+
+static /*HDR*/
+/**
+ * @brief
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+int win32_create_file( const char *dev, HANDLE *ph )
+{
+ static const char prefix[] = "\\\\.\\";
+
+ size_t len = strlen( prefix ) + strlen( dev ) + 1;
+ char *tmp_name;
+ int rc = MBG_ERR_UNSPEC;
+
+ tmp_name = (char *) malloc( len );
+
+ if ( tmp_name == NULL ) // unable to allocate memory
+ {
+ rc = MBG_ERR_NO_MEM;
+ goto out;
+ }
+
+ strcpy( tmp_name, prefix );
+ strcat( tmp_name, dev );
+
+ *ph = CreateFile( tmp_name, GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, //##++++++++++++++ | FILE_FLAG_WRITE_THROUGH,
+ NULL );
+
+ if ( *ph == INVALID_HANDLE_VALUE )
+ {
+ rc = mbg_win32_last_err_to_mbg( GetLastError(), "CreateFile failed in win32_create_file" );
+ goto out_free;
+ }
+
+ rc = MBG_SUCCESS;
+
+out_free:
+ free( tmp_name );
+
+out:
+ return rc;
+
+} // win32_create_file
+
+#endif // defined( MBG_TGT_WIN32 )
+
+
+
+static /*HDR*/
+/**
+ * @brief
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgserio_close_port_by_handle( MBG_PORT_HANDLE *p )
+{
+ if ( *p != MBG_INVALID_PORT_HANDLE )
+ {
+ #if defined( MBG_TGT_CVI )
+
+ CloseCom( *p );
+
+ #elif defined( MBG_TGT_WIN32 )
+
+ CloseHandle( *p );
+
+ #elif defined( MBG_TGT_POSIX )
+
+ close( *p );
+
+ #elif defined( MBG_TGT_DOS )
+ #if defined( _USE_V24TOOLS )
+
+ v24close( *p );
+
+ #else
+
+ #error Target DOS requires v24tools for serial I/O.
+
+ #endif
+
+ #else
+
+ #error This target OS is not supported.
+
+ #endif
+
+ *p = MBG_INVALID_PORT_HANDLE;
+ }
+
+ return MBG_SUCCESS;
+
+} // mbgserio_close_port_by_handle
+
+
+
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev )
+/**
+ * @brief
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgserio_close( SERIAL_IO_STATUS *pst )
{
- MBG_PORT_HANDLE port_handle;
+ if ( pst->port_handle != MBG_INVALID_PORT_HANDLE )
+ {
+ MBG_PORT_HANDLE port_handle = pst->port_handle;
+
+ mbgserio_flush_tx( port_handle );
+
+ #if defined( MBG_TGT_WIN32 )
+
+ SetCommState( port_handle, &pst->old_dcb );
+ SetCommTimeouts( port_handle, &pst->old_commtimeouts );
+
+ #elif defined( MBG_TGT_POSIX )
+
+ tcsetattr( port_handle, TCSANOW, &pst->old_tio );
+
+ #endif
+
+ return mbgserio_close_port_by_handle( &pst->port_handle );
+ }
+
+ return MBG_SUCCESS;
+
+} // mbgserio_close
+
+
+
+/*HDR*/
+/**
+ * @brief
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev )
+{
+ MBG_PORT_HANDLE port_handle = MBG_INVALID_PORT_HANDLE;
+ int rc = MBG_ERR_UNSPEC;
#if defined( MBG_TGT_CVI )
{
- int data_bits = 8; //##++
+ int data_bits = 8; //##+++++++++++++++
int parity_code = 0;
int baud_rate = 19200;
int stop_bits = 1;
@@ -124,102 +313,173 @@ _MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev
// Under CVI the port handle passed to OpenComConfig and used furtheron
// corresponds to the COM port number, e.g. 1 for COM1, so we extract
// the number from the device name passed as parameter.
- port_handle = 0;
len = strlen( dev );
for ( i = 0; i < len; i++ )
{
char c = dev[i];
+
if ( c >= '0' && c <= '9' )
break;
}
if ( i == len )
- return MBGSERIO_INV_CFG; // no numeric substring found
-
+ {
+ rc = MBG_ERR_INV_PARM; // no numeric substring found
+ goto out;
+ }
port_handle = atoi( &dev[i] );
- rc = OpenComConfig (port_handle, NULL, baud_rate, parity_code, data_bits, stop_bits, 8192, 1024); //##++
+ rc = OpenComConfig( port_handle, NULL, baud_rate, parity_code, data_bits, stop_bits, 8192, 1024 ); //##++
+
if ( rc < 0 )
- goto fail;
+ {
+ port_handle = MBG_INVALID_PORT_HANDLE;
+ rc = MBG_ERR_UNSPEC; // translate rc ?
+ goto out;
+ }
- pst->port_handle = port_handle;
+ rc = SetComTime( port_handle, 1.0 ); //##+++++++ WTF?
- SetComTime( port_handle, 1.0 ); //##++
- SetXMode( port_handle, 0 );
+ if ( rc < 0 )
+ {
+ rc = MBG_ERR_UNSPEC; //##+++++ translate rc ?
+ goto out_close;
+ }
+
+ rc = SetXMode( port_handle, 0 );
+
+ if ( rc < 0 )
+ {
+ rc = MBG_ERR_UNSPEC; //##+++++ translate rc ?
+ goto out_close;
+ }
}
#elif defined( MBG_TGT_WIN32 )
{
- static const char *prefix = "\\\\.\\";
-
COMMTIMEOUTS commtimeouts;
- int len = strlen( prefix ) + strlen( dev ) + 1;
- char *tmp_name = (char *) malloc( len );
-
- if ( tmp_name == NULL ) // unable to allocate memory
- goto fail;
-
-
- strcpy( tmp_name, prefix );
- strcat( tmp_name, dev );
-
- port_handle = CreateFile( tmp_name, GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
- NULL );
-
- free( tmp_name );
-
- if ( port_handle == INVALID_HANDLE_VALUE )
- goto fail;
+ DCB dcb;
+ rc = win32_create_file( dev, &port_handle );
- pst->port_handle = port_handle;
+ if ( rc != MBG_SUCCESS )
+ goto out;
- // save original settings
+ // save settings found at startup
pst->old_dcb.DCBlength = sizeof( pst->old_dcb );
GetCommState( port_handle, &pst->old_dcb );
GetCommTimeouts( port_handle, &pst->old_commtimeouts );
+ GetCommProperties( port_handle, &pst->comm_prop );
+
+ #if 0 // fields provided by the Windows DCB structure
+ DWORD DCBlength; /* sizeof(DCB) */
+ DWORD BaudRate; /* Baudrate at which running */
+ DWORD fBinary: 1; /* Binary Mode (skip EOF check) */
+ DWORD fParity: 1; /* Enable parity checking */
+ DWORD fOutxCtsFlow:1; /* CTS handshaking on output */
+ DWORD fOutxDsrFlow:1; /* DSR handshaking on output */
+ DWORD fDtrControl:2; /* DTR Flow control */
+ DWORD fDsrSensitivity:1; /* DSR Sensitivity */
+ DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
+ DWORD fOutX: 1; /* Enable output X-ON/X-OFF */
+ DWORD fInX: 1; /* Enable input X-ON/X-OFF */
+ DWORD fErrorChar: 1; /* Enable Err Replacement */
+ DWORD fNull: 1; /* Enable Null stripping */
+ DWORD fRtsControl:2; /* Rts Flow control */
+ DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
+ DWORD fDummy2:17; /* Reserved */
+ WORD wReserved; /* Not currently used */
+ WORD XonLim; /* Transmit X-ON threshold */
+ WORD XoffLim; /* Transmit X-OFF threshold */
+ BYTE ByteSize; /* Number of bits/byte, 4-8 */
+ BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */
+ BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */
+ char XonChar; /* Tx and Rx X-ON character */
+ char XoffChar; /* Tx and Rx X-OFF character */
+ char ErrorChar; /* Error replacement char */
+ char EofChar; /* End of Input character */
+ char EvtChar; /* Received Event character */
+ WORD wReserved1; /* Fill for now. */
+ #endif
// configure our settings
+ dcb = pst->old_dcb; // current settings as default
+ dcb.fOutxCtsFlow = FALSE; // CTS output flow control
+ dcb.fOutxDsrFlow = FALSE; // DSR output flow control
+ dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable DTR
+ dcb.fDsrSensitivity = FALSE; // don't require DSR input active
+ //##++ TODO: more missing here
+ dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable RTS for C28COM
+ dcb.fOutX = FALSE;
+
+ if ( !SetCommState( port_handle, &dcb ) )
+ {
+ rc = mbg_get_last_error( "SetCommState failed in mbgserio_open" );
+ goto out_close;
+ }
+
memset( &commtimeouts, 0, sizeof( commtimeouts ) );
- SetCommTimeouts( port_handle, &commtimeouts );
- #if defined( MBGSERIO_IN_BUFFER_SIZE ) && defined( MBGSERIO_OUT_BUFFER_SIZE )
- SetupComm( port_handle, MBGSERIO_IN_BUFFER_SIZE, MBGSERIO_OUT_BUFFER_SIZE );
+ if ( !SetCommTimeouts( port_handle, &commtimeouts ) )
+ {
+ rc = mbg_get_last_error( "SetCommTimeout failed in mbgserio_open" );
+ goto out_close;
+ }
+
+ #if !defined( MBGSERIO_IN_BUFFER_SIZE )
+ #define MBGSERIO_IN_BUFFER_SIZE 2048
+ #endif
+
+ #if !defined( MBGSERIO_OUT_BUFFER_SIZE )
+ #define MBGSERIO_OUT_BUFFER_SIZE 2048
#endif
- PurgeComm( port_handle, PURGE_TXABORT|PURGE_TXCLEAR );
- PurgeComm( port_handle, PURGE_RXABORT|PURGE_RXCLEAR );
+ if ( !SetupComm( port_handle, MBGSERIO_IN_BUFFER_SIZE, MBGSERIO_OUT_BUFFER_SIZE ) )
+ {
+ rc = mbg_get_last_error( "SetupComm failed in mbgserio_open" );
+ goto out_close;
+ }
- //##++ mbgextio_set_console_control_handler();
+ PurgeComm( port_handle, PURGE_TXABORT | PURGE_TXCLEAR );
+ PurgeComm( port_handle, PURGE_RXABORT | PURGE_RXCLEAR );
+
+ //##++ TODO: mbgextio_set_console_control_handler() ?
}
- #elif defined( MBG_TGT_UNIX )
+ #elif defined( MBG_TGT_POSIX )
{
// Open as not controlling TTY to prevent from being
// killed if CTRL-C is received.
// O_NONBLOCK is the same as O_NDELAY.
- port_handle = _mbg_open( dev, O_RDWR | O_NOCTTY | O_NONBLOCK );
+ int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
- //##++ TODO: Under Unix a serial port can by default be opened
- // by several processes. However, we don't want that, so we
- // should care about this using a lock file for the device
- // and/or setting the TIOCEXCL flag (which unfortunately
- // is not an atomic operation with open()).
+ #if defined( O_CLOEXEC )
+ flags |= O_CLOEXEC;
+ #endif
- if ( port_handle < 0 ) // check errno for the reason
- goto fail;
+ port_handle = open( dev, flags ); // returns -1 on error
+ if ( port_handle < 0 )
+ {
+ rc = mbg_get_last_error( "open failed in mbgserio_open" );
+ port_handle = MBG_INVALID_PORT_HANDLE;
+ goto out;
+ }
- pst->port_handle = port_handle;
+ //##++ TODO: Under Unix a serial port can by default be opened
+ // by several processes. However, we don't want that, so we
+ // should care about this using a lock file for the device
+ // and/or setting the TIOCEXCL flag (which unfortunately
+ // is not an atomic operation with open()).
/* save current device settings */
- tcgetattr( port_handle, &pst->oldtio );
+ if ( tcgetattr( port_handle, &pst->old_tio ) < 0 )
+ {
+ rc = mbg_get_last_error( "tcgetattr failed in mbgserio_open" );
+ goto out_close;
+ }
- // atexit( port_deinit );
+ //##++ atexit( port_deinit );
fflush( stdout ); //##++
setvbuf( stdout, NULL, _IONBF, 0 );
@@ -230,9 +490,11 @@ _MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev
port_handle = v24open( (char *) dev, OPEN_MODE );
if ( port_handle < 0 )
- goto fail;
+ {
+ rc = MBG_ERR_UNSPEC; // translate rc ?
+ goto out;
+ }
- pst->port_handle = port_handle;
v24settimeout( port_handle, 1 );
}
#else
@@ -247,67 +509,81 @@ _MBG_API_ATTR int _MBG_API mbgserio_open( SERIAL_IO_STATUS *pst, const char *dev
#endif
- return 0;
+ rc = MBG_SUCCESS;
+ goto out;
+out_close:
+ mbgserio_close_port_by_handle( &port_handle ); // also sets port handle invalid
-fail:
- pst->port_handle = MBG_INVALID_PORT_HANDLE;
- return MBGSERIO_FAIL;
+out:
+ pst->port_handle = port_handle;
+ return rc;
} // mbgserio_open
-/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgserio_close( SERIAL_IO_STATUS *pst )
+#if 0 && defined( MBG_TGT_POSIX )
+
+static /*HDR*/
+int scandir_filter_serial_port( const struct dirent *pde )
{
- if ( pst->port_handle != MBG_INVALID_PORT_HANDLE )
- {
- MBG_PORT_HANDLE port_handle = pst->port_handle;
+ static const char dev_name_1[] = "ttyS";
+ static const char dev_name_2[] = "ttyUSB";
+ char tmp_str[100];
+ SERIAL_IO_STATUS iost;
+ int rc;
- #if defined( MBG_TGT_CVI )
+ int l;
- CloseCom( port_handle );
+ l = strlen( dev_name_1 );
- #elif defined( MBG_TGT_WIN32 )
+ if ( strncmp( pde->d_name, dev_name_1, l ) == 0 )
+ goto check;
- SetCommState( port_handle, &pst->old_dcb );
- SetCommTimeouts( port_handle, &pst->old_commtimeouts );
- CloseHandle( port_handle );
- #elif defined( MBG_TGT_UNIX )
+ l = strlen( dev_name_2 );
- tcsetattr( port_handle, TCSANOW, &pst->oldtio );
- close( port_handle );
+ if ( strncmp( pde->d_name, dev_name_2, l ) == 0 )
+ goto check;
- #elif defined( MBG_TGT_DOS )
- #if defined( _USE_V24TOOLS )
+ return 0;
- v24close( port_handle );
+check:
+ // if the first character after the search string is not a digit
+ // then the search result is not what we want
+ if ( pde->d_name[l] < '0' || pde->d_name[l] > '9' )
+ return 0;
- #else
+ snprintf( tmp_str, sizeof( tmp_str ), "%s/%s", dev_dir, pde->d_name );
- #error Target DOS requires v24tools for serial I/O.
+ rc = mbgserio_open( &iost, tmp_str );
- #endif
+ if ( rc < 0 )
+ {
+ #if defined( DEBUG )
+ fprintf( stderr, "failed to open %s: %i\n", tmp_str, rc );
+ #endif
- #else
+ return 0;
+ }
- #error This target OS is not supported.
+ #if defined( DEBUG )
+ fprintf( stderr, "port %s opened successfully\n", tmp_str );
+ #endif
- #endif
+ mbgserio_close( &iost );
- pst->port_handle = MBG_INVALID_PORT_HANDLE;
- }
+ return 1;
- return 0;
+} // scandir_filter_serial_port
-} // mbgserio_close
+#endif // defined( MBG_TGT_POSIX )
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, int max_devs )
+_NO_MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, int max_devs )
{
MBG_STR_LIST *list_head;
int n = 0;
@@ -318,24 +594,94 @@ _MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, in
list_head = (*list);
+
+#if 0 && defined( MBG_TGT_POSIX )
+
+ struct dirent **namelist;
+
+ n = scandir( dev_dir, &namelist, scandir_filter_serial_port, versionsort );
+
+ if ( n < 0 )
+ perror( "scandir" );
+ else
+ {
+ for ( i = 0; i < n; i++ )
+ {
+ printf( "%s/%s\n", dev_dir, namelist[i]->d_name );
+ free( namelist[i] );
+ }
+
+ free( namelist );
+ }
+
+#elif 0 && defined( MBG_TGT_POSIX )
+
+ DIR *pd = opendir( dev_dir );
+
+ if ( pd )
+ {
+ struct dirent *pde;
+
+ while ( ( pde = readdir( pd ) ) != NULL )
+ {
+ if ( strncmp( pde->d_name, "ttyS", 4 ) == 0 )
+ goto found;
+
+ if ( strncmp( pde->d_name, "ttyUSB", 6 ) == 0 )
+ goto found;
+
+ continue;
+
+found:
+ fprintf( stderr, "found /dev/%s\n", pde->d_name );
+ }
+
+ closedir( pd );
+ }
+
+#else
+
for ( i = 0; i < max_devs; i++ )
{
- SERIAL_IO_STATUS iost;
char dev_name[100] = { 0 };
int rc;
#if defined( MBG_TGT_WIN32 )
+
+ HANDLE h = INVALID_HANDLE_VALUE;
+
sprintf( dev_name, "COM%i", i + 1 );
+ rc = win32_create_file( dev_name, &h );
+
+ // If access is denied then the port exists but is in use
+ if ( rc != MBG_SUCCESS && rc != MBG_ERR_ACCESS )
+ continue; // memory allocation error
+
+ if ( h != INVALID_HANDLE_VALUE )
+ CloseHandle( h );
+
#elif defined( MBG_TGT_LINUX )
+
+ SERIAL_IO_STATUS iost;
sprintf( dev_name, "/dev/ttyS%i", i );
- #endif
+ rc = mbgserio_open( &iost, dev_name );
- rc = mbgserio_open( &iost, dev_name );
+ if ( rc < 0 )
+ {
+ sprintf( dev_name, "/dev/ttyUSB%i", i );
+
+ rc = mbgserio_open( &iost, dev_name );
+
+ if ( rc < 0 )
+ continue;
+ }
+
+ mbgserio_close( &iost );
+
+ #endif
- if ( rc < 0 )
- continue;
- mbgserio_close( &iost );
+ // add the device name to the list
(*list)->s = (char *) malloc( strlen( dev_name ) + 1 );
strcpy( (*list)->s, dev_name );
@@ -355,6 +701,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, in
free( *list );
list_head = NULL;
}
+#endif
*list = list_head;
@@ -365,7 +712,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_setup_port_str_list( MBG_STR_LIST **list, in
/*HDR*/
-_MBG_API_ATTR void _MBG_API _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list )
+_NO_MBG_API_ATTR void _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list )
{
int i = 0;
@@ -406,18 +753,23 @@ _MBG_API_ATTR void _MBG_API _MBG_API mbgserio_free_str_list( MBG_STR_LIST *list
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
+/**
+ * @brief
+ *
+ * @return One of the @ref MBG_RETURN_CODES
+ */
+_NO_MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
uint32_t baud_rate, const char *framing )
{
MBG_PORT_HANDLE port_handle = pst->port_handle;
const char *cp;
+ int rc = MBG_ERR_UNSPEC;
#if defined( MBG_TGT_CVI )
{
int data_bits = 8;
- int parity_code = 0;
+ int parity_code = 0;
int stop_bits = 1;
- int rc;
// setup framing.
for ( cp = framing; *cp; cp++ )
@@ -449,24 +801,31 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
break;
default:
- return MBGSERIO_INV_CFG; // invalid framing string
+ rc = MBG_ERR_INV_PARM; // invalid framing string
+ goto out;
}
}
- rc = OpenComConfig( port_handle, NULL, baud_rate, parity_code,
- data_bits, stop_bits, 8192, 1024 );
+ rc = OpenComConfig( port_handle, NULL, baud_rate, parity_code,
+ data_bits, stop_bits, 8192, 1024 );
if ( rc < 0 )
- return rc;
+ {
+ rc = MBG_ERR_INV_PARM;
+ goto out;
+ }
- SetComTime( port_handle, 1.0 ); //##++
+ SetComTime( port_handle, 1.0 ); //##++++++++ check rc ?
SetXMode( port_handle, 0 );
}
#elif defined( MBG_TGT_WIN32 )
{
DCB dcb;
- dcb.DCBlength = sizeof( DCB ) ;
- GetCommState( port_handle, &dcb ) ;
+ // get current settings
+ dcb.DCBlength = sizeof( DCB );
+ GetCommState( port_handle, &dcb ); //##++++++++++++++++ check rc?
+
+ // update changed settings
dcb.BaudRate = baud_rate;
@@ -503,27 +862,19 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
break;
default:
- return MBGSERIO_INV_CFG; // invalid framing string
+ rc = MBG_ERR_INV_PARM; // invalid framing string
+ goto out;
}
}
-
- dcb.fOutxCtsFlow = FALSE; // CTS output flow control
- dcb.fOutxDsrFlow = FALSE; // DSR output flow control
- dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable DTR for C28COM
- dcb.fDsrSensitivity = FALSE; // don't require DSR input active
- //##++ more missing here
- dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable RTS for C28COM
- dcb.fOutX = FALSE;
-
- SetCommState ( port_handle, &dcb );
+ SetCommState( port_handle, &dcb ); //##++++++++ check rc
}
- #elif defined( MBG_TGT_UNIX )
+ #elif defined( MBG_TGT_POSIX )
{
tcflag_t c_cflag = 0;
struct termios tio;
- tcgetattr( port_handle, &tio );
+ rc = tcgetattr( port_handle, &tio ); //##+++++++++++++++++ check rc
// setup transmission speed
switch( baud_rate )
@@ -537,8 +888,16 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
case 19200: c_cflag = B19200; break;
case 38400: c_cflag = B38400; break;
case 57600: c_cflag = B57600; break;
+ #if defined( B115200 )
+ case 115200: c_cflag = B115200; break;
+ #endif
+ #if defined( B230400 )
+ case 230400: c_cflag = B230400; break;
+ #endif
- default: return MBGSERIO_INV_CFG; // invalid
+ default:
+ rc = MBG_ERR_INV_PARM; // invalid
+ goto out;
}
#if 0 //##++ This should be used preferably for portability reasons
@@ -549,7 +908,9 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
// setup framing.
for ( cp = framing; *cp; cp++ )
{
- switch ( _toupper( *cp ) )
+ char c = toupper( *cp );
+
+ switch ( c )
{
case '7': c_cflag |= CS7; break;
case '8': c_cflag |= CS8; break;
@@ -561,7 +922,9 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
case '1': break;
case '2': c_cflag |= CSTOPB; break;
- default: return MBGSERIO_INV_CFG; // invalid framing string
+ default:
+ rc = MBG_ERR_INV_PARM; // invalid
+ goto out;
}
}
@@ -572,7 +935,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
// (POSIX says that the baud speed is stored in the termios structure
// without specifying where precisely, and provides cfgetispeed() and
// cfsetispeed() for getting at it. Some systems use bits selected
- // by CBAUD in c_cflag, other systems use separate fields,
+ // by CBAUD in c_cflag, other systems use separate fields,
// e.g. sg_ispeed and sg_ospeed.)
// CSIZE Character size mask. Values are CS5, CS6, CS7, or CS8.
// CSTOPB Set two stop bits, rather than one.
@@ -595,17 +958,17 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
// Setup input flags. The following flags are defined:
// IGNBRK Ignore BREAK condition on input
- // BRKINT If IGNBRK is set, a BREAK is ignored. If it is not set
- // but BRKINT is set, then a BREAK causes the input and output
+ // BRKINT If IGNBRK is set, a BREAK is ignored. If it is not set
+ // but BRKINT is set, then a BREAK causes the input and output
// queues to be flushed, and if the terminal is the controlling
- // terminal of a foreground process group, it will cause a
+ // terminal of a foreground process group, it will cause a
// SIGINT to be sent to this foreground process group. When
// neither IGNBRK nor BRKINT are set, a BREAK reads as a NUL
// character, except when PARMRK is set, in which case it reads
// as the sequence \377 \0 \0.
// IGNPAR Ignore framing errors and parity errors.
- // PARMRK If IGNPAR is not set, prefix a character with a parity error
- // framing error with \377 \0. If neither IGNPAR nor PARMRK or
+ // PARMRK If IGNPAR is not set, prefix a character with a parity error
+ // framing error with \377 \0. If neither IGNPAR nor PARMRK or
// is set, read a character with a parity error or framing error as \0.
// INPCK Enable input parity checking.
// ISTRIP Strip off eighth bit.
@@ -636,14 +999,14 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
// ONOCR Don't output CR at column 0.
// ONLRET Don't output CR.
// OFILL Send fill characters for a delay, rather than using a timed delay.
- // OFDEL (not in POSIX) Fill character is ASCII DEL (0177). If unset,
+ // OFDEL (not in POSIX) Fill character is ASCII DEL (0177). If unset,
// fill character is ASCII NUL.
// NLDLY Newline delay mask. Values are NL0 and NL1.
// CRDLY Carriage return delay mask. Values are CR0, CR1, CR2, or CR3.
- // TABDLY Horizontal tab delay mask. Values are TAB0, TAB1, TAB2, TAB3
- // (or XTABS). A value of TAB3, that is, XTABS, expands tabs to
+ // TABDLY Horizontal tab delay mask. Values are TAB0, TAB1, TAB2, TAB3
+ // (or XTABS). A value of TAB3, that is, XTABS, expands tabs to
// spaces (with tab stops every eight columns).
- // BSDLY Backspace delay mask. Values are BS0 or BS1.
+ // BSDLY Backspace delay mask. Values are BS0 or BS1.
// (Has never been implemented.)
// VTDLY Vertical tab delay mask. Values are VT0 or VT1.
// FFDLY Form feed delay mask. Values are FF0 or FF1.
@@ -657,53 +1020,53 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
// EOF, EOL, EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS, and
// WERASE, and buffers by lines.
// XCASE (not in POSIX; not supported under Linux) If ICANON is also
- // set, terminal is uppercase only. Input is converted to
- // lowercase, except for characters preceded by \. On output,
- // uppercase characters are preceded by \ and lowercase
+ // set, terminal is uppercase only. Input is converted to
+ // lowercase, except for characters preceded by \. On output,
+ // uppercase characters are preceded by \ and lowercase
// characters are converted to uppercase.
// ECHO Echo input characters.
- // ECHOE If ICANON is also set, the ERASE character erases the preceding
+ // ECHOE If ICANON is also set, the ERASE character erases the preceding
// input character, and WERASE erases the preceding word.
// ECHOK If ICANON is also set, the KILL character erases the current line.
// ECHONL If ICANON is also set, echo the NL character even if ECHO is not set.
// ECHOCTL (not in POSIX) If ECHO is also set, ASCII control signals
// other than TAB, NL, START, and STOP are echoed as ^X, where
- // X is the character with ASCII code 0x40 greater than the control
+ // X is the character with ASCII code 0x40 greater than the control
// signal. For example, character 0x08 (BS) is echoed as ^H.
- // ECHOPRT (not in POSIX) If ICANON and IECHO are also set, characters are
+ // ECHOPRT (not in POSIX) If ICANON and IECHO are also set, characters are
// printed as they are being erased.
- // ECHOKE (not in POSIX) If ICANON is also set, KILL is echoed by erasing
+ // ECHOKE (not in POSIX) If ICANON is also set, KILL is echoed by erasing
// each character on the line, as specified by ECHOE and ECHOPRT.
// DEFECHO (not in POSIX) Echo only when a process is reading.
// FLUSHO (not in POSIX; not supported under Linux) Output is being flushed.
// This flag is toggled by typing the DISCARD character.
// NOFLSH Disable flushing the input and output queues when generating the
// SIGINT, SIGQUIT and SIGSUSP signals.
- // TOSTOP Send the SIGTTOU signal to the process group of a background
+ // TOSTOP Send the SIGTTOU signal to the process group of a background
// process which tries to write to its controlling terminal.
// PENDIN (not in POSIX; not supported under Linux) All characters in the
- // input queue are reprinted when the next character is read.
+ // input queue are reprinted when the next character is read.
// (bash handles typeahead this way.)
// IEXTEN Enable implementation-defined input processing. This flag, as
- // well as ICANON must be enabled for the special characters EOL2,
+ // well as ICANON must be enabled for the special characters EOL2,
// LNEXT, REPRINT, WERASE to be interpreted, and for the IUCLC flag
// to be effective.
tio.c_lflag = 0;
// VINTR (003, ETX, Ctrl-C, or also 0177, DEL, rubout) Interrupt character.
- // Send a SIGINT signal. Recognized when ISIG is set, and then not
+ // Send a SIGINT signal. Recognized when ISIG is set, and then not
// passed as input.
// VQUIT (034, FS, Ctrl-\) Quit character. Send SIGQUIT signal. Recognized
// when ISIG is set, and then not passed as input.
// VERASE (0177, DEL, rubout, or 010, BS, Ctrl-H, or also #) Erase character.
// This erases the previous not-yet-erased character, but does not erase
- // past EOF or beginning-of-line. Recognized when ICANON is set,
+ // past EOF or beginning-of-line. Recognized when ICANON is set,
// and then not passed as input.
// VKILL (025, NAK, Ctrl-U, or Ctrl-X, or also @) Kill character. This erases
// the input since the last EOF or beginning-of-line. Recognized when
// ICANON is set, and then not passed as input.
- // VEOF (004, EOT, Ctrl-D) End-of-file character. More precisely: this
+ // VEOF (004, EOT, Ctrl-D) End-of-file character. More precisely: this
// character causes the pending tty buffer to be sent to the waiting
// user program without waiting for end-of-line. If it is the first
// character of the line, the read() in the user program returns 0,
@@ -722,9 +1085,9 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
// typed. Recognized when IXON is set, and then not passed as input.
// VSUSP (032, SUB, Ctrl-Z) Suspend character. Send SIGTSTP signal. Recognized
// when ISIG is set, and then not passed as input.
- // VDSUSP (not in POSIX; not supported under Linux; 031, EM, Ctrl-Y) Delayed
+ // VDSUSP (not in POSIX; not supported under Linux; 031, EM, Ctrl-Y) Delayed
// suspend character: send SIGTSTP signal when the character is read by
- // the user program. Recognized when IEXTEN and ISIG are set, and the
+ // the user program. Recognized when IEXTEN and ISIG are set, and the
// system supports job control, and then not passed as input.
// VLNEXT (not in POSIX; 026, SYN, Ctrl-V) Literal next. Quotes the next input
// character, depriving it of a possible special meaning. Recognized
@@ -733,18 +1096,18 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
// and IEXTEN are set, and then not passed as input.
// VREPRINT (not in POSIX; 022, DC2, Ctrl-R) Reprint unread characters. Recognized
// when ICANON and IEXTEN are set, and then not passed as input.
- // VDISCARD (not in POSIX; not supported under Linux; 017, SI, Ctrl-O) Toggle:
+ // VDISCARD (not in POSIX; not supported under Linux; 017, SI, Ctrl-O) Toggle:
// start/stop discarding pending output. Recognized when IEXTEN is set,
// and then not passed as input.
// VSTATUS (not in POSIX; not supported under Linux; status request: 024, DC4, Ctrl-T).
// Setting up c_cc[VMIN] and c_cc[VTIME]:
- // If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before
+ // If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before
// the read is satisfied. As TIME is zero, the timer is not used.
// If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will be
- // satisfied if a single character is read, or TIME is exceeded
- // (t = TIME *0.1 s). If TIME is exceeded, no character will be
+ // satisfied if a single character is read, or TIME is exceeded
+ // (t = TIME *0.1 s). If TIME is exceeded, no character will be
// returned.
// If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The
// read will be satisfied if MIN characters are received, or the
@@ -752,8 +1115,8 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
// every time a character is received and only becomes active after
// the first character has been received.
// If MIN = 0 and TIME = 0, read will be satisfied immediately. The number of
- // characters currently available, or the number of characters
- // requested will be returned. You could issue a
+ // characters currently available, or the number of characters
+ // requested will be returned. You could issue a
// fcntl(fd, F_SETFL, FNDELAY); before reading to get the same result.
// setup control characters for non-blocking read
@@ -761,8 +1124,8 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
tio.c_cc[VTIME] = 0;
// now clean the modem line and activate the settings for modem
- tcflush( port_handle, TCIFLUSH );
- tcsetattr( port_handle, TCSANOW, &tio );
+ rc = tcflush( port_handle, TCIFLUSH );
+ rc = tcsetattr( port_handle, TCSANOW, &tio ); //##+++++++++ check rc ?
fflush( stdout );
setvbuf( stdout, NULL, _IONBF, 0 );
@@ -789,7 +1152,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
case 'N':
case 'E':
case 'O':
- parity = *cp;
+ parity = c;
break;
case '1':
@@ -798,11 +1161,12 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
break;
default:
- return MBGSERIO_INV_CFG; // invalid framing string
+ rc = MBG_ERR_INV_PARM; // invalid framing string
+ goto out;
}
}
- v24setparams( port_handle, baud_rate, datab, parity, stopb );
+ v24setparams( port_handle, baud_rate, datab, parity, stopb ); //##++++++++++++++ check rc?
}
#else
@@ -816,87 +1180,199 @@ _MBG_API_ATTR int _MBG_API mbgserio_set_parms( SERIAL_IO_STATUS *pst,
#endif
- return 0;
+ rc = MBG_SUCCESS;
-} // mbgserio_set_parms
+out:
+ return rc;
+} // mbgserio_set_parms
-#if defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_CVI )
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgserio_read( MBG_PORT_HANDLE h, void *buffer, unsigned int count )
+_NO_MBG_API_ATTR int _MBG_API mbgserio_read( MBG_PORT_HANDLE h, void *buffer, unsigned int count )
{
- BOOL fReadStat;
- COMSTAT ComStat;
- DWORD dwErrorFlags;
- DWORD dwLength;
+ #if defined( MBG_TGT_CVI )
- ClearCommError( h, &dwErrorFlags, &ComStat );
+ return ComRd( h, (char *) buffer, count );
- if ( dwErrorFlags ) // transmission error (parity, framing, etc.)
- return MBGSERIO_FAIL;
+ #elif defined( MBG_TGT_WIN32 )
+ BOOL fReadStat;
+ COMSTAT ComStat;
+ DWORD dwErrorFlags;
+ DWORD dwLength;
- dwLength = min( (DWORD) count, ComStat.cbInQue );
+ ClearCommError( h, &dwErrorFlags, &ComStat );
- if ( dwLength )
- {
- fReadStat = ReadFile( h, buffer, dwLength, &dwLength, NULL );
+ if ( dwErrorFlags ) // transmission error (parity, framing, etc.)
+ return MBG_ERR_IO; //##+++++++++++++++++++++++++
- if ( !fReadStat )
- return MBGSERIO_FAIL;
- }
- return dwLength;
+ dwLength = min( (DWORD) count, ComStat.cbInQue );
-} // mbgserio_read
+ if ( dwLength )
+ {
+ fReadStat = ReadFile( h, buffer, dwLength, &dwLength, NULL );
+
+ if ( !fReadStat )
+ return MBG_ERR_IO; //##++++++++++++++
+ }
+
+ return dwLength;
+ #elif defined( MBG_TGT_POSIX )
+
+ return read( h, buffer, count );
+
+ #elif defined( MBG_TGT_DOS ) && defined( _USE_V24TOOLS )
+
+ return v24read( h, buffer, count );
+
+ #else
+
+ #error mbgserio_read() not implemented for this target
+
+ #endif
+
+} // mbgserio_read
+/* //##+++++++++++++++++ need to check all targets
+ * @return one of the MBG_ERROR_CODES on error, else number of bytes written
+ */
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgserio_write( MBG_PORT_HANDLE h, const void *buffer, unsigned int count )
+_NO_MBG_API_ATTR int _MBG_API mbgserio_write( MBG_PORT_HANDLE h, const void *buffer, unsigned int count )
{
- BOOL fWriteStat;
- COMSTAT ComStat;
- DWORD dwErrorFlags;
- DWORD dwThisBytesWritten;
- DWORD dwTotalBytesWritten = 0;
+ #if defined( MBG_TGT_CVI )
- while ( dwTotalBytesWritten < (DWORD) count )
- {
- dwThisBytesWritten = 0;
+ return ComWrt( h, (char *) buffer, count );
+
+ #elif defined( MBG_TGT_WIN32 )
- fWriteStat = WriteFile( h, ( (char *) buffer ) + dwTotalBytesWritten,
- count - dwTotalBytesWritten,
- &dwThisBytesWritten, NULL );
- if ( !fWriteStat )
+ BOOL fWriteStat;
+ COMSTAT ComStat;
+ DWORD dwErrorFlags;
+ DWORD dwThisBytesWritten;
+ DWORD dwTotalBytesWritten = 0;
+
+ while ( dwTotalBytesWritten < (DWORD) count )
{
- #if defined( _DEBUG )
- DWORD dw = GetLastError();
- #endif
- break; //##++ Error: Unable to write
+ dwThisBytesWritten = 0;
+
+ fWriteStat = WriteFile( h, ( (char *) buffer ) + dwTotalBytesWritten,
+ count - dwTotalBytesWritten,
+ &dwThisBytesWritten, NULL );
+ if ( !fWriteStat )
+ return mbg_get_last_error( "write failed in mbgserio_write" );
+
+ dwTotalBytesWritten += dwThisBytesWritten;
+
+ ClearCommError( h, &dwErrorFlags, &ComStat );
+
+ if ( dwErrorFlags )
+ {
+ // Possible errors:
+ //
+ // CE_RXOVER 0x0001 // Receive Queue overflow
+ // CE_OVERRUN 0x0002 // Receive Overrun Error, next character(s) lost
+ // CE_RXPARITY 0x0004 // Receive Parity Error
+ // CE_FRAME 0x0008 // Receive Framing error
+ // CE_BREAK 0x0010 // Break Detected
+ // CE_TXFULL 0x0100 // TX Queue is full
+ // CE_PTO 0x0200 // LPTx Timeout
+ // CE_IOE 0x0400 // LPTx I/O Error
+ // CE_DNS 0x0800 // LPTx Device not selected
+ // CE_OOP 0x1000 // LPTx Out-Of-Paper
+ // CE_MODE 0x8000 // Requested mode unsupported
+ //
+ // Except CE_TXFULL these are usually RX error flags,
+ // so we just ignore them.
+ }
}
- dwTotalBytesWritten += dwThisBytesWritten;
+ return dwTotalBytesWritten;
- ClearCommError( h, &dwErrorFlags, &ComStat );
+ #elif defined( MBG_TGT_POSIX )
- if ( dwErrorFlags )
- break; //#++ Error: Check flags
- }
+ int rc = write( h, buffer, count ); // returns -1 on error, else number of byte written
- return dwTotalBytesWritten;
+ if ( rc == -1 )
+ return mbg_get_last_error( "write failed in mbgserio_write" );
+
+ return rc;
+
+ #elif defined( MBG_TGT_DOS ) && defined( _USE_V24TOOLS )
+
+ return v24write( h, buffer, count );
+
+ #else
+
+ #error mbgserio_write() not implemented for this target
+
+ #endif
} // mbgserio_write
-#endif // defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_CVI )
+
+
+/*HDR*/
+_NO_MBG_API_ATTR void _MBG_API mbgserio_flush_tx( MBG_PORT_HANDLE h )
+{
+ #if defined( MBG_TGT_CVI )
+
+ FlushOutQ( h );
+
+ #elif defined( MBG_TGT_WIN32 )
+
+ #if defined( DEBUG )
+ printf( "Flushing TX buffers ...\n" );
+ #endif
+
+ FlushFileBuffers( h );
+
+ #if ( 1 && defined( DEBUG ) ) //##++++++++++++++
+ {
+ COMSTAT ComStat;
+ DWORD dwErrorFlags;
+
+ for (;;)
+ {
+ ClearCommError( h, &dwErrorFlags, &ComStat );
+
+ printf( "ErrFlags: %04X, out queue: %u\n", dwErrorFlags, ComStat.cbOutQue );
+
+ if ( ComStat.cbOutQue == 0 )
+ break;
+
+ Sleep( 1 );
+ }
+ }
+ #endif
+
+ //##++++ Sleep( 500 );
+
+ #elif defined( MBG_TGT_POSIX )
+
+ tcdrain( h );
+
+ #elif defined( MBG_TGT_DOS ) && defined( _USE_V24TOOLS )
+
+ v24flush( h, SND );
+
+ #else
+
+ #error mbgserio_flush_tx() not implemented for this target
+
+ #endif
+
+} // mbgserio_flush_tx
/*HDR*/
-_MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer,
- uint count, ulong char_timeout )
+_NO_MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer,
+ uint count, ulong char_timeout )
{
int n_bytes;
@@ -904,14 +1380,25 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer,
struct timeval tv_char_timeout;
fd_set fds;
+ int max_fd;
int rc;
- mbgserio_msec_to_timeval( char_timeout, &tv_char_timeout );
+ mbg_msec_to_timeval( char_timeout, &tv_char_timeout );
FD_ZERO( &fds );
FD_SET( h, &fds );
- rc = select( h + 1, &fds, NULL, NULL, &tv_char_timeout );
+ #if defined( MBG_TGT_WIN32 )
+ // Under Windows an fd is a handle which can't simply
+ // be converted to an int, but the first argument of
+ // select() is ignored under Windows anyway, so we just
+ // set max_fd to 0.
+ max_fd = 0;
+ #else
+ max_fd = h;
+ #endif
+
+ rc = select( max_fd + 1, &fds, NULL, NULL, &tv_char_timeout );
if ( rc < 0 ) // error
goto fail;
@@ -920,7 +1407,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer,
goto timeout;
// data is available
- n_bytes = _mbgserio_read( h, buffer, count );
+ n_bytes = mbgserio_read( h, buffer, count );
#else
MBG_TMO_TIME tmo;
@@ -929,7 +1416,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer,
for (;;) // wait to read one new char
{
- n_bytes = _mbgserio_read( h, buffer, count );
+ n_bytes = mbgserio_read( h, buffer, count );
if ( n_bytes > 0 ) // new char(s) received
break;
@@ -940,7 +1427,7 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer,
if ( mbg_tmo_curr_time_is_after( &tmo ) )
goto timeout;
- #if defined( MBG_TGT_UNIX )
+ #if defined( MBG_TGT_POSIX )
usleep( 10 * 1000 );
#endif
}
@@ -949,10 +1436,10 @@ _MBG_API_ATTR int _MBG_API mbgserio_read_wait( MBG_PORT_HANDLE h, void *buffer,
return n_bytes;
timeout:
- return MBGSERIO_TIMEOUT;
+ return MBG_ERR_TIMEOUT;
fail:
- return MBGSERIO_FAIL;
+ return MBG_ERR_IO;
} // mbgserio_read_wait