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( <cDeviceName> [, <lCreate> = .F. ] ) -> <nPort>
* 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<n>:" prefix, in form like:
COM<n>:[<com_params>]
<n> is port number or port name prefixed with "$" character.
<com_params> 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.
This commit is contained in:
@@ -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( <cDeviceName> [, <lCreate> = .F. ] ) -> <nPort>
|
||||
|
||||
* 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<n>:" prefix, in form like:
|
||||
COM<n>:[<com_params>]
|
||||
<n> is port number or port name prefixed with "$" character.
|
||||
<com_params> 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
|
||||
|
||||
435
contrib/hbcomio/comio.c
Normal file
435
contrib/hbcomio/comio.c
Normal file
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Harbour Project source code:
|
||||
* I/O driver for serial port streams
|
||||
*
|
||||
* Copyright 2014 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
|
||||
* 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
|
||||
3
contrib/hbcomio/hbcomio.hbc
Normal file
3
contrib/hbcomio/hbcomio.hbc
Normal file
@@ -0,0 +1,3 @@
|
||||
description=I/O driver for serial port streams
|
||||
|
||||
libs=${_HB_DYNPREF}${hb_name}${_HB_DYNSUFF}
|
||||
10
contrib/hbcomio/hbcomio.hbp
Normal file
10
contrib/hbcomio/hbcomio.hbp
Normal file
@@ -0,0 +1,10 @@
|
||||
-hblib
|
||||
-inc
|
||||
|
||||
-o${hb_name}
|
||||
|
||||
-w3 -es2
|
||||
|
||||
${hb_name}.hbx
|
||||
|
||||
comio.c
|
||||
@@ -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
|
||||
|
||||
@@ -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() );
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
196
src/rtl/hbcom.c
196
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 <os2.h>
|
||||
#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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user