diff --git a/ChangeLog.txt b/ChangeLog.txt index 704d9b42da..af13afd2a3 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,48 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2014-03-10 18:59 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * contrib/hbtcpio/tcpio.c + * use default timeout defined in initial hostname string in read/write + operations + + * include/hbapicom.h + * src/rtl/hbcom.c + + added new C function: + int hb_comFindPort( const char * pszDevName, HB_BOOL fCreate ); + It check if given port name is already defined and if not and second + parameter fCreate is TRUE then it allocates such port in one of last + free slots. On success port number is returned. If port cannot be + found or created 0 is returned. + + * include/harbour.hbx + * src/rtl/hbcomhb.c + + added new PRG function: + hb_comFindPort( [, = .F. ] ) -> + + * contrib/hbplist.txt + + contrib/hbcomio/comio.c + + contrib/hbcomio/hbcomio.hbc + + contrib/hbcomio/hbcomio.hbp + + added new Harbour FILE IO redirector. + It recognizes and process names with "COM:" prefix, in form like: + COM:[] + is port number or port name prefixed with "$" character. + may contain serial port parameters like baud rate, stop + and data bits, parity and flow control (XON,XOFF,CTS, RTS,DST,DTR). + As delimiter comma "," is accepted. + This redirector can be used in different subsystems using Harbour + FILE IO and stream read/write operations, i.e. + REQUEST HB_COMIO + SET PRINTER TO COM2:38400,N81,XONXOFF + can be used to connect to serial printers. + Please remember that redirectors like NETIO can be used as wrapper + to other redirectors so code like: + pFile := hb_vfOpen( "NET:192.168.0.1:::COM1:9600,8N1" ) + opens 1-st serial port on the server and + pFile := hb_vfOpen( "NET:192.168.0.1:::COM$/dev/ttyUSB0:9600,8N1" ) + opens "/dev/ttyUSB0" serial device on the server. + 2014-03-08 14:00 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * src/compiler/hbcmplib.c * src/rtl/filesys.c diff --git a/contrib/hbcomio/comio.c b/contrib/hbcomio/comio.c new file mode 100644 index 0000000000..33567f79ce --- /dev/null +++ b/contrib/hbcomio/comio.c @@ -0,0 +1,435 @@ +/* + * Harbour Project source code: + * I/O driver for serial port streams + * + * Copyright 2014 Przemyslaw Czerpak + * www - http://harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.txt. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +/* this has to be declared before hbapifs.h is included */ +#define _HB_FILE_IMPLEMENTATION_ + +#include "hbapi.h" +#include "hbapifs.h" +#include "hbapierr.h" +#include "hbinit.h" + +#include "hbapicom.h" + +typedef struct _HB_FILE +{ + const HB_FILE_FUNCS * pFuncs; + int port; + int timeout; + HB_BOOL fRead; + HB_BOOL fWrite; +} +HB_FILE; + +static PHB_FILE s_fileNew( int port, int timeout, HB_BOOL fRead, HB_BOOL fWrite ); + +static int s_fileGetValue( const char * pszName, int * piLen ) +{ + int iLen = 0, iValue = 0; + + while( HB_ISDIGIT( pszName[ iLen ] ) ) + iValue = iValue * 10 + ( pszName[ iLen++ ] - '0' ); + + *piLen = iLen; + return iValue; +} + +static int s_filePortParams( const char * pszName, int * piTimeout, + int * piBaud, int * piParity, + int * piSize, int * piStop, + int * piFlow ) +{ + int iPort = 0, iLen, iValue; + + *piTimeout = -1; + *piBaud = *piParity = *piSize = *piStop = *piFlow = 0; + + pszName += 3; + if( *pszName == '$' ) + { + const char * pszParams = strchr( pszName, ':' ); + + if( pszParams != NULL && pszParams - pszName > 1 ) + { + char * pszPort = hb_strndup( pszName + 1, pszParams - pszName - 1 ); + + iPort = hb_comFindPort( pszPort, HB_TRUE ); + hb_xfree( pszPort ); + pszName = pszParams; + } + } + else + { + while( HB_ISDIGIT( *pszName ) ) + iPort = iPort * 10 + ( *pszName++ - '0' ); + } + + while( iPort > 0 && *pszName ) + { + if( HB_ISDIGIT( *pszName ) ) + { + iValue = s_fileGetValue( pszName, &iLen ); + if( iLen == 1 ) + { + if( iValue >= 1 && iValue <= 2 && *piStop == 0 ) + *piStop = iValue; + else if( iValue >= 5 && iValue <= 8 && *piSize == 0 ) + *piSize = iValue; + else + iPort = -1; + } + else if( iLen == 2 && *piStop == 0 && *piSize == 0 ) + { + if( pszName[ 0 ] >= '1' && pszName[ 0 ] <= '2' && + pszName[ 1 ] >= '5' && pszName[ 1 ] <= '8' ) + { + *piStop = pszName[ 0 ] - '0'; + *piSize = pszName[ 1 ] - '0'; + } + else if( pszName[ 0 ] >= '5' && pszName[ 0 ] <= '8' && + pszName[ 1 ] >= '1' && pszName[ 1 ] <= '2' ) + { + *piStop = pszName[ 1 ] - '0'; + *piSize = pszName[ 0 ] - '0'; + } + else if( *piBaud ) + iPort = -1; + else + *piBaud = iValue; + } + else if( *piBaud ) + iPort = -1; + else + *piBaud = iValue; + pszName += iLen; + } + else if( HB_ISALPHA( *pszName ) ) + { + if( hb_strnicmp( pszName, "RTS", 3 ) == 0 ) + { + *piFlow |= HB_COM_FLOW_IRTSCTS; + pszName += 3; + } + else if( hb_strnicmp( pszName, "CTS", 3 ) == 0 ) + { + *piFlow |= HB_COM_FLOW_ORTSCTS; + pszName += 3; + } + else if( hb_strnicmp( pszName, "DTR", 3 ) == 0 ) + { + *piFlow |= HB_COM_FLOW_IDTRDSR; + pszName += 3; + } + else if( hb_strnicmp( pszName, "DSR", 3 ) == 0 ) + { + *piFlow |= HB_COM_FLOW_ODTRDSR; + pszName += 3; + } + else if( hb_strnicmp( pszName, "DCD", 3 ) == 0 ) + { + *piFlow |= HB_COM_FLOW_DCD; + pszName += 3; + } + else if( hb_strnicmp( pszName, "XOFF", 4 ) == 0 ) + { + *piFlow |= HB_COM_FLOW_XOFF; + pszName += 4; + } + else if( hb_strnicmp( pszName, "XON", 3 ) == 0 ) + { + *piFlow |= HB_COM_FLOW_XON; + pszName += 3; + } + else if( *piParity == 0 && ! HB_ISALPHA( pszName[ 1 ] ) ) + { + switch( *pszName ) + { + case 'N': + case 'n': + case 'E': + case 'e': + case 'O': + case 'o': + case 'S': + case 's': + case 'M': + case 'm': + *piParity = HB_TOUPPER( *pszName ); + pszName++; + break; + default: + iPort = -1; + break; + } + } + else + iPort = -1; + } + else if( *pszName == ':' || *pszName == ',' || *pszName == ' ' ) + pszName++; + else + iPort = -1; + } + + if( *piBaud == 0 ) + *piBaud = 9600; + if( *piParity == 0 ) + *piParity = 'N'; + if( *piSize == 0 ) + *piSize = 8; + if( *piStop == 0 ) + *piStop = 1; + + return iPort; +} + +static HB_BOOL s_fileAccept( const char * pszFileName ) +{ + if( HB_TOUPPER( pszFileName[ 0 ] ) == 'C' && + HB_TOUPPER( pszFileName[ 1 ] ) == 'O' && + HB_TOUPPER( pszFileName[ 2 ] ) == 'M' ) + { + if( pszFileName[ 3 ] == '$' ) + return strchr( pszFileName + 4, ':' ) != NULL; + else if( pszFileName[ 3 ] >= '1' && pszFileName[ 3 ] <= '9' ) + { + pszFileName += 4; + while( HB_ISDIGIT( *pszFileName ) ) + ++pszFileName; + return *pszFileName == ':'; + } + } + return HB_FALSE; +} + +static PHB_FILE s_fileOpen( const char * pszName, const char * pszDefExt, + HB_USHORT uiExFlags, + const char * pPaths, PHB_ITEM pError ) +{ + PHB_FILE pFile = NULL; + HB_ERRCODE errcode = 0; + int iPort, iTimeout, iBaud, iParity, iSize, iStop, iFlow; + HB_BOOL fRead, fWrite; + + HB_SYMBOL_UNUSED( pszDefExt ); + HB_SYMBOL_UNUSED( pPaths ); + + fRead = fWrite = HB_TRUE; + iPort = s_filePortParams( pszName, &iTimeout, + &iBaud, &iParity, &iSize, &iStop, &iFlow ); + if( iPort > 0 ) + { + if( hb_comOpen( iPort ) == 0 && + hb_comInit( iPort, iBaud, iParity, iSize, iStop ) == 0 && + hb_comFlowControl( iPort, NULL, iFlow ) == 0 ) + { + switch( uiExFlags & 0x3 ) + { + case FO_READ: + fWrite = HB_FALSE; + break; + case FO_WRITE: + fRead = HB_FALSE; + break; + } + pFile = s_fileNew( iPort, iTimeout, fRead, fWrite ); + } + else + errcode = hb_comGetError( iPort ); + } + else + errcode = HB_COM_ERR_WRONGPORT; + + hb_fsSetError( errcode ); + + if( pError ) + { + hb_errPutFileName( pError, pszName ); + if( pFile == NULL ) + { + hb_errPutOsCode( pError, errcode ); + hb_errPutGenCode( pError, ( HB_ERRCODE ) EG_OPEN ); + } + } + + return pFile; +} + +static void s_fileClose( PHB_FILE pFile ) +{ + hb_comClose( pFile->port ); + hb_fsSetError( hb_comGetError( pFile->port ) ); + hb_xfree( pFile ); +} + +static HB_SIZE s_fileRead( PHB_FILE pFile, void * data, + HB_SIZE nSize, HB_MAXINT timeout ) +{ + HB_ERRCODE errcode; + long lRead = 0; + + if( pFile->fRead ) + { + lRead = nSize > LONG_MAX ? LONG_MAX : ( long ) nSize; + if( timeout == -1 ) + timeout = pFile->timeout; + lRead = hb_comRecv( pFile->port, data, lRead, timeout ); + errcode = hb_comGetError( pFile->port ); + } + else + errcode = HB_COM_ERR_ACCESS; + + hb_fsSetError( errcode ); + + return HB_MAX( lRead, 0 ); +} + +static HB_SIZE s_fileWrite( PHB_FILE pFile, const void * data, + HB_SIZE nSize, HB_MAXINT timeout ) +{ + HB_ERRCODE errcode; + long lSent = 0; + + if( pFile->fWrite ) + { + lSent = nSize > LONG_MAX ? LONG_MAX : ( long ) nSize; + if( timeout == -1 ) + timeout = pFile->timeout; + lSent = hb_comSend( pFile->port, data, lSent, timeout ); + errcode = hb_comGetError( pFile->port ); + } + else + errcode = HB_COM_ERR_ACCESS; + + hb_fsSetError( errcode ); + + return HB_MAX( 0, lSent ); +} + +static HB_BOOL s_fileConfigure( PHB_FILE pFile, int iIndex, PHB_ITEM pValue ) +{ + HB_SYMBOL_UNUSED( pFile ); + HB_SYMBOL_UNUSED( iIndex ); + HB_SYMBOL_UNUSED( pValue ); + + return HB_FALSE; +} + +static HB_FHANDLE s_fileHandle( PHB_FILE pFile ) +{ + return pFile ? hb_comGetDeviceHandle( pFile->port ) : FS_ERROR; +} + +static HB_FILE_FUNCS s_fileFuncs = +{ + s_fileAccept, + + NULL, /* s_fileExists */ + NULL, /* s_fileDelete */ + NULL, /* s_fileRename */ + NULL, /* s_fileCopy */ + + NULL, /* s_fileDirExists */ + NULL, /* s_fileDirMake */ + NULL, /* s_fileDirRemove */ + NULL, /* s_fileDirSpace */ + NULL, /* s_fileDirectory */ + + NULL, /* s_fileTimeGet */ + NULL, /* s_fileTimeSet */ + NULL, /* s_fileAttrGet */ + NULL, /* s_fileAttrSet */ + + NULL, /* s_fileLink */ + NULL, /* s_fileLinkSym */ + NULL, /* s_fileLinkRead */ + + s_fileOpen, + s_fileClose, + NULL, /* s_fileLock */ + NULL, /* s_fileLockTest */ + s_fileRead, + s_fileWrite, + NULL, /* s_fileReadAt */ + NULL, /* s_fileWriteAt */ + NULL, /* s_fileTruncAt */ + NULL, /* s_fileSeek */ + NULL, /* s_fileSize */ + NULL, /* s_fileEof */ + NULL, /* s_fileFlush */ + NULL, /* s_fileCommit */ + s_fileConfigure, + s_fileHandle +}; + +static PHB_FILE s_fileNew( int port, int timeout, HB_BOOL fRead, HB_BOOL fWrite ) +{ + PHB_FILE pFile = ( PHB_FILE ) hb_xgrab( sizeof( HB_FILE ) ); + + pFile->pFuncs = &s_fileFuncs; + pFile->port = port; + pFile->timeout = timeout; + pFile->fRead = fRead; + pFile->fWrite = fWrite; + + return pFile; +} + +HB_FUNC( HB_COMIO ) { ; } + + +HB_CALL_ON_STARTUP_BEGIN( _hb_file_comio_init_ ) + hb_fileRegisterPart( &s_fileFuncs ); +HB_CALL_ON_STARTUP_END( _hb_file_comio_init_ ) + +#if defined( HB_PRAGMA_STARTUP ) + #pragma startup _hb_file_comio_init_ +#elif defined( HB_DATASEG_STARTUP ) + #define HB_DATASEG_BODY HB_DATASEG_FUNC( _hb_file_comio_init_ ) + #include "hbiniseg.h" +#endif diff --git a/contrib/hbcomio/hbcomio.hbc b/contrib/hbcomio/hbcomio.hbc new file mode 100644 index 0000000000..a1b87afb71 --- /dev/null +++ b/contrib/hbcomio/hbcomio.hbc @@ -0,0 +1,3 @@ +description=I/O driver for serial port streams + +libs=${_HB_DYNPREF}${hb_name}${_HB_DYNSUFF} diff --git a/contrib/hbcomio/hbcomio.hbp b/contrib/hbcomio/hbcomio.hbp new file mode 100644 index 0000000000..42338a8e1b --- /dev/null +++ b/contrib/hbcomio/hbcomio.hbp @@ -0,0 +1,10 @@ +-hblib +-inc + +-o${hb_name} + +-w3 -es2 + +${hb_name}.hbx + +comio.c diff --git a/contrib/hbplist.txt b/contrib/hbplist.txt index 2fc02e5371..a5bca1d98c 100644 --- a/contrib/hbplist.txt +++ b/contrib/hbplist.txt @@ -6,6 +6,7 @@ hbblat/hbblat.hbp hbblink/hbblink.hbp hbbz2/hbbz2.hbp # uses: bz2 (locally hosted) hbcairo/hbcairo.hbp +hbcomio/hbcomio.hbp hbcomm/hbcomm.hbp hbct/hbct.hbp hbcups/hbcups.hbp diff --git a/contrib/hbtcpio/tcpio.c b/contrib/hbtcpio/tcpio.c index d0d028683f..1ed2522c85 100644 --- a/contrib/hbtcpio/tcpio.c +++ b/contrib/hbtcpio/tcpio.c @@ -187,6 +187,8 @@ static HB_SIZE s_fileRead( PHB_FILE pFile, void * data, if( ! pFile->fEof ) { lRead = nSize > LONG_MAX ? LONG_MAX : ( long ) nSize; + if( timeout == -1 ) + timeout = pFile->timeout; lRead = hb_socketRecv( pFile->sd, data, lRead, 0, timeout ); errcode = hb_socketGetError(); @@ -216,6 +218,8 @@ static HB_SIZE s_fileWrite( PHB_FILE pFile, const void * data, { long lSend = nSize > LONG_MAX ? LONG_MAX : ( long ) nSize; + if( timeout == -1 ) + timeout = pFile->timeout; lSend = hb_socketSend( pFile->sd, data, lSend, 0, timeout ); hb_fsSetError( hb_socketGetError() ); diff --git a/include/harbour.hbx b/include/harbour.hbx index 16a25de502..6aedc27f85 100644 --- a/include/harbour.hbx +++ b/include/harbour.hbx @@ -350,6 +350,7 @@ DYNAMIC hb_ColorToN DYNAMIC hb_comClose DYNAMIC hb_comDiscardChar DYNAMIC hb_comErrorChar +DYNAMIC hb_comFindPort DYNAMIC hb_comFlowChars DYNAMIC hb_comFlowControl DYNAMIC hb_comFlowSet diff --git a/include/hbapicom.h b/include/hbapicom.h index 6fe103e751..4a77ffa465 100644 --- a/include/hbapicom.h +++ b/include/hbapicom.h @@ -64,6 +64,7 @@ HB_EXTERN_BEGIN #define HB_COM_OPEN 2 extern HB_EXPORT int hb_comLastNum( void ); +extern HB_EXPORT int hb_comFindPort( const char * pszDevName, HB_BOOL fCreate ); extern HB_EXPORT int hb_comOpen( int iPort ); extern HB_EXPORT int hb_comClose( int iPort ); extern HB_EXPORT int hb_comInit( int iPort, int iBaud, int iParity, int iSize, int iStop ); @@ -86,7 +87,7 @@ extern HB_EXPORT int hb_comDiscardChar( int iPort, int iChar ); extern HB_EXPORT int hb_comErrorChar( int iPort, int iChar ); extern HB_EXPORT int hb_comOutputState( int iPort ); extern HB_EXPORT int hb_comInputState( int iPort ); -extern HB_EXPORT int hb_comSetDevice( int iPort, const char * szDevName ); +extern HB_EXPORT int hb_comSetDevice( int iPort, const char * pszDevName ); extern HB_EXPORT const char * hb_comGetDevice( int iPort, char * buffer, int size ); extern HB_EXPORT HB_FHANDLE hb_comGetDeviceHandle( int iPort ); diff --git a/src/rtl/hbcom.c b/src/rtl/hbcom.c index 28db48df44..67285dd793 100644 --- a/src/rtl/hbcom.c +++ b/src/rtl/hbcom.c @@ -51,12 +51,6 @@ #endif #include "hbapi.h" -#include "hbapifs.h" -#include "hbapiitm.h" -#include "hbapicom.h" -#include "hbvm.h" -#include "hbinit.h" -#include "hbdate.h" #if defined( HB_OS_UNIX ) && ( ! defined( __WATCOMC__ ) || __WATCOMC__ > 1290 ) && \ ! defined( HB_OS_SYMBIAN ) /* || defined( __DJGPP__ ) */ @@ -108,6 +102,14 @@ # include #endif +#include "hbapifs.h" +#include "hbapiitm.h" +#include "hbapicom.h" +#include "hbvm.h" +#include "hbinit.h" +#include "hbdate.h" +#include "hbthread.h" + typedef struct { #if defined( HB_HAS_TERMIOS ) @@ -133,6 +135,10 @@ typedef struct } HB_COM, * PHB_COM; +static HB_CRITICAL_NEW( s_comMtx ); +#define HB_COM_LOCK() do { hb_threadEnterCriticalSection( &s_comMtx ) +#define HB_COM_UNLOCK() hb_threadLeaveCriticalSection( &s_comMtx ); } while( 0 ) + static HB_COM s_comList[ HB_COM_PORT_MAX ]; static void hb_comCloseAll( void ) @@ -173,7 +179,7 @@ static PHB_COM hb_comGetPort( int iPort, int iStatus ) return NULL; } -static const char * hb_comGetName( PHB_COM pCom, char * buffer, int size ) +static const char * hb_comGetNameRaw( PHB_COM pCom, char * buffer, int size ) { const char * name = pCom->name; @@ -186,14 +192,14 @@ static const char * hb_comGetName( PHB_COM pCom, char * buffer, int size ) hb_snprintf( buffer, size, "/dev/tty%dp0", pCom->port ); # elif defined( HB_OS_AIX ) hb_snprintf( buffer, size, "/dev/tty%d", pCom->port ); +# elif defined( HB_OS_MINIX ) + hb_snprintf( buffer, size, "/dev/tty%02d", pCom->port - 1 ); # elif defined( HB_OS_IRIX ) hb_snprintf( buffer, size, "/dev/ttyf%d", pCom->port ); # elif defined( HB_OS_DIGITAL_UNIX ) hb_snprintf( buffer, size, "/dev/ttyf%02d", pCom->port ); # elif defined( HB_OS_DARWIN ) hb_snprintf( buffer, size, "/dev/cuaa%d", pCom->port - 1 ); -# elif defined( HB_OS_MINIX ) - hb_snprintf( buffer, size, "/dev/tty%02d", pCom->port - 1 ); # else /* defined( HB_OS_LINUX ) || defined( HB_OS_CYGWIN ) || ... */ hb_snprintf( buffer, size, "/dev/ttyS%d", pCom->port - 1 ); # endif @@ -208,6 +214,174 @@ static const char * hb_comGetName( PHB_COM pCom, char * buffer, int size ) return name; } +static const char * hb_comGetName( PHB_COM pCom, char * buffer, int size ) +{ + const char * name; + + HB_COM_LOCK(); + name = hb_comGetNameRaw( pCom, buffer, size ); + if( name != buffer ) + name = hb_strncpy( buffer, name, size - 1 ); + HB_COM_UNLOCK(); + + return name; +} + +static int hb_comGetPortNum( const char * pszName ) +{ + int iPort = 0; + +#if defined( HB_OS_UNIX ) +# if defined( HB_OS_SUNOS ) + if( strncmp( pszName, "/dev/tty", 8 ) == 0 && + pszName[ 8 ] >= 'a' && pszName[ 9 ] == '\0' ) + iPort = pszName[ 8 ] - 'a' + 1; +# else + int iLen = 0; +# if defined( HB_OS_HPUX ) || defined( HB_OS_AIX ) || defined( HB_OS_MINIX ) + if( strncmp( pszName, "/dev/tty", 8 ) == 0 ) + iLen = 8; +# elif defined( HB_OS_IRIX ) || defined( HB_OS_DIGITAL_UNIX ) + if( strncmp( pszName, "/dev/ttyf", 9 ) == 0 ) + iLen = 9; +# elif defined( HB_OS_DARWIN ) + if( strncmp( pszName, "/dev/cuaa", 9 ) == 0 ) + iLen = 9; +# else /* defined( HB_OS_LINUX ) || defined( HB_OS_CYGWIN ) || ... */ + if( strncmp( pszName, "/dev/ttyS", 9 ) == 0 ) + iLen = 9; +# endif + if( iLen > 0 ) + { + pszName += iLen; + while( HB_ISDIGIT( *pszName ) ) + iPort = iPort * 10 + ( *pszName++ - '0' ); + +# if ! defined( HB_OS_HPUX ) && \ + ! defined( HB_OS_AIX ) && \ + ! defined( HB_OS_IRIX ) && \ + ! defined( HB_OS_DIGITAL_UNIX ) + ++iPort; +# endif + +# if defined( HB_OS_HPUX ) + if( strcmp( pszName, "p0" ) != 0 ) +# else + if( *pszName != '\0' ) +# endif + iPort = 0; + } +# endif +#else + if( pszName[ 0 ] == '\\' && pszName[ 1 ] == '\\' && + pszName[ 2 ] == '.' && pszName[ 3 ] == '\\' ) + pszName += 4; + if( HB_TOUPPER( pszName[ 0 ] ) == 'C' && + HB_TOUPPER( pszName[ 1 ] ) == 'O' && + HB_TOUPPER( pszName[ 2 ] ) == 'M' && + pszName[ 3 ] >= '1' && pszName[ 3 ] <= '9' ) + { + pszName += 3; + while( HB_ISDIGIT( *pszName ) ) + iPort = iPort * ( 10 + *pszName++ - '0' ); + if( *pszName != '\0' ) + iPort = 0; + } +#endif + + return iPort; +} + +static HB_BOOL hb_comPortCmp( const char * pszDevName1, const char * pszDevName2 ) +{ +#if defined( HB_OS_UNIX ) + return strcmp( pszDevName1, pszDevName2 ) == 0; +#else +# if defined( HB_OS_WIN ) + if( pszDevName1[ 0 ] == '\\' && pszDevName1[ 1 ] == '\\' && + pszDevName1[ 2 ] == '.' && pszDevName1[ 3 ] == '\\' ) + pszDevName1 += 4; + if( pszDevName2[ 0 ] == '\\' && pszDevName2[ 1 ] == '\\' && + pszDevName2[ 2 ] == '.' && pszDevName2[ 3 ] == '\\' ) + pszDevName2 += 4; +# endif + return hb_stricmp( pszDevName1, pszDevName2 ) == 0; +#endif +} + +int hb_comFindPort( const char * pszDevName, HB_BOOL fCreate ) +{ + char buffer[ HB_COM_DEV_NAME_MAX ]; + PHB_COM pCom; + int iPort; + + if( pszDevName == NULL || *pszDevName == '\0' ) + return 0; + + iPort = hb_comGetPortNum( pszDevName ); + HB_COM_LOCK(); + if( iPort > 0 ) + { + pCom = hb_comGetPort( iPort, HB_COM_ANY ); + if( pCom == NULL || + ! hb_comPortCmp( hb_comGetNameRaw( pCom, buffer, sizeof( buffer ) ), + pszDevName ) ) + iPort = 0; + } + + if( iPort == 0 ) + { + int iPortFree = 0; + + for( iPort = HB_COM_PORT_MAX; iPort > 0; --iPort ) + { + pCom = &s_comList[ iPort - 1 ]; + if( pCom->name == NULL ) + { + if( iPortFree == 0 && iPort > 16 ) + iPortFree = iPort; + } + else if( hb_comPortCmp( pCom->name, pszDevName ) ) + break; + } +#if defined( HB_OS_UNIX ) + if( iPort == 0 && fCreate && access( pszDevName, F_OK ) == 0 ) +#else + if( iPort == 0 && fCreate ) +#endif + { + if( iPortFree != 0 ) + iPort = iPortFree; + else + { + for( iPort = HB_COM_PORT_MAX; iPort > 0; --iPort ) + { + pCom = &s_comList[ iPort - 1 ]; + if( ( pCom->status & HB_COM_OPEN ) == 0 ) + { + if( pCom->name ) + { + hb_xfree( pCom->name ); + pCom->name = NULL; + } + break; + } + } + } + if( iPort != 0 ) + { + pCom = &s_comList[ iPort - 1 ]; + if( ! hb_comPortCmp( hb_comGetNameRaw( pCom, buffer, sizeof( buffer ) ), + pszDevName ) ) + pCom->name = hb_strdup( pszDevName ); + } + } + } + HB_COM_UNLOCK(); + + return iPort; +} + const char * hb_comGetDevice( int iPort, char * buffer, int size ) { PHB_COM pCom = hb_comGetPort( iPort, HB_COM_ANY ); @@ -230,9 +404,11 @@ int hb_comSetDevice( int iPort, const char * szDevName ) if( pCom ) { + HB_COM_LOCK(); if( pCom->name ) hb_xfree( pCom->name ); - pCom->name = szDevName ? hb_strdup( szDevName ) : NULL; + pCom->name = szDevName && *szDevName ? hb_strdup( szDevName ) : NULL; + HB_COM_UNLOCK(); } return pCom ? 0 : -1; diff --git a/src/rtl/hbcomhb.c b/src/rtl/hbcomhb.c index d8febdb40e..09601bfa31 100644 --- a/src/rtl/hbcomhb.c +++ b/src/rtl/hbcomhb.c @@ -58,6 +58,7 @@ * hb_comGetDeviceHandle( nPort ) --> nHandle | F_ERROR * hb_comGetError( nPort ) --> nError * hb_comGetOSError( nPort ) --> nError + * hb_comFindPort( cDeviceName [, lCreate = .F. ] ) --> nPort * hb_comInit( nPort, nBaud, cParity, nSize, nStop ) --> lSuccess * hb_comInputCount( nPort ) --> nCount * hb_comInputState( nPort ) --> nState @@ -143,6 +144,12 @@ HB_FUNC( HB_COMGETOSERROR ) hb_retni( hb_comGetOsError( hb_parni( 1 ) ) ); } +HB_FUNC( HB_COMFINDPORT ) +{ + hb_retni( hb_comFindPort( hb_parc( 1 ), hb_parl( 2 ) ) ); +} + + HB_FUNC( HB_COMINIT ) { hb_retl( hb_comInit( hb_parni( 1 ), hb_parni( 2 ), HB_ISCHAR( 3 ) ? hb_parc( 3 )[ 0 ] : 0,