diff options
Diffstat (limited to 'mbglib/common/mbgserio.c')
-rw-r--r-- | mbglib/common/mbgserio.c | 929 |
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 |