--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialPort.st Thu Feb 02 17:22:51 2006 +0100
@@ -0,0 +1,544 @@
+"
+ COPYRIGHT (c) 2006 by eXept Software AG
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+
+"{ Package: 'stx:libbasic2' }"
+
+NonPositionableExternalStream subclass:#SerialPort
+ instanceVariableNames:'portName baudRate stopBitsType parityType dataBits
+ inFlowCtrlType outFlowCtrlType xOnChar xOffChar'
+ classVariableNames:'DefaultPortName'
+ poolDictionaries:''
+ category:'Streams-External'
+!
+
+!SerialPort primitiveDefinitions!
+%{
+
+#include "stxOSDefs.h"
+
+#ifdef WIN32
+
+# undef __BEGIN_INTERRUPTABLE__
+# undef __END_INTERRUPTABLE__
+# define __BEGIN_INTERRUPTABLE__ ..
+# define __END_INTERRUPTABLE__ ..
+
+# define WRAP_STDIO
+
+# define PORT_FROM_FD(fd) (_get_osfhandle(fd))
+# define closePort(port) closeHandle(port)
+# define SERIALPORT HANDLE
+
+#else /* not WIN32 */
+
+# define PORT_FROM_FD(fd) (fd)
+# define closePort(port) close(port)
+# define SERIALPORT int
+
+#endif /* WIN32 */
+
+# define PORT_FROM_FILE(f) (PORT_FROM_FD(fileno(f)))
+# define PORT_FROM_FILE_OBJECT(f) (PORT_FROM_FILE(__FILEVal(f)))
+
+#include <stdio.h>
+#include <errno.h>
+
+/*
+ * on some systems errno is a macro ... check for it here
+ */
+#ifndef errno
+ extern errno;
+#endif
+
+#ifdef USE_H_ERRNO
+# ifndef h_errno
+ extern h_errno;
+# endif
+#endif
+
+#ifdef DEBUG
+# define DBGPRINTF(x) { if (__debugging__) printf x; }
+# define DBGFPRINTF(x) { if (__debugging__) fprintf x; }
+#else
+# define DBGPRINTF(x) /* as nothing */
+# define DBGFPRINTF(x) /* as nothing */
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif
+#ifndef WIN32
+typedef int BOOL;
+#endif
+
+
+%}
+! !
+
+!SerialPort primitiveVariables!
+%{
+static int __debugging__ = 0;
+%}
+! !
+
+!SerialPort class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 2006 by eXept Software AG
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+documentation
+"
+ This class provides access to serial ports
+"
+!
+
+examples
+"
+ example (get help info from an nntp server):
+ [exBegin]
+ ... to be added ...
+ [exEnd]
+"
+! !
+
+!SerialPort class methodsFor:'defaults'!
+
+defaultPortName
+ DefaultPortName notNil ifTrue:[^ DefaultPortName ].
+
+ OperatingSystem isMSDOSlike ifTrue:[
+ ^ 'COM1'
+ ].
+ ^ '/dev/cua0'
+! !
+
+!SerialPort class methodsFor:'instance creation'!
+
+portName:portName
+ baudRate:baudRateOrNil stopBitsType:stopBitsTypeOrNil
+ parityType:parityTypeOrNil dataBits:dataBitsOrNil
+ inFlowCtrlType:inFlowCtrlTypeOrNil outFlowCtrlType:outFlowCtrlTypeOrNil
+ xOnChar:xOnCharOrNil xOffChar:xOffCharOrNil
+
+ "arguments are self describing; nil values mean: leave setting as is"
+
+ ^ (self new
+ setPortName:portName
+ baudRate:baudRateOrNil stopBitsType:stopBitsTypeOrNil
+ parityType:parityTypeOrNil dataBits:dataBitsOrNil
+ inFlowCtrlType:inFlowCtrlTypeOrNil outFlowCtrlType:outFlowCtrlTypeOrNil
+ xOnChar:xOnCharOrNil xOffChar:xOffCharOrNil) open
+!
+
+new
+ "create a serial port"
+
+ ^ super new buffered:false
+! !
+
+!SerialPort class methodsFor:'debugging'!
+
+debug:aBoolean
+ "turn on/off internal debugprints.
+ This method is for ST/X debugging only and
+ may be removed in later versions"
+
+%{ /* NOCONTEXT */
+
+ __debugging__ = (aBoolean == true);
+%}
+ "
+ SerialPort debug:true
+ SerialPort debug:false
+ "
+! !
+
+!SerialPort methodsFor:'accessing'!
+
+setPortName:portNameArg
+ baudRate:baudRateOrNil stopBitsType:stopBitsTypeOrNil
+ parityType:parityTypeOrNil dataBits:dataBitsOrNil
+ inFlowCtrlType:inFlowCtrlTypeOrNil outFlowCtrlType:outFlowCtrlTypeOrNil
+ xOnChar:xOnCharOrNil xOffChar:xOffCharOrNil
+
+ portName := portNameArg.
+ baudRate := baudRateOrNil.
+ stopBitsType := stopBitsTypeOrNil.
+ parityType := parityTypeOrNil.
+ dataBits := dataBitsOrNil.
+ inFlowCtrlType := inFlowCtrlTypeOrNil.
+ outFlowCtrlType := outFlowCtrlTypeOrNil.
+ xOnChar := xOnCharOrNil.
+ xOffChar := xOffCharOrNil.
+! !
+
+!SerialPort protectedMethodsFor:'low level'!
+
+closeFile
+ "low level close"
+
+%{
+ OBJ t;
+
+ t = __INST(filePointer);
+ if (t != nil) {
+ FILE *fp;
+ SERIALPORT port;
+
+ __INST(filePointer) = nil;
+ fp = __FILEVal(t);
+ port = PORT_FROM_FILE(fp);
+
+# ifdef xxDO_WRAP_CALLS
+ { int ret;
+
+ do {
+ __threadErrno = 0;
+ ret = STX_C_CALL1("fclose", fclose, fp);
+ } while ((ret < 0) && (__threadErrno == EINTR));
+
+# ifdef WIN32
+ do {
+ __threadErrno = 0;
+ ret = STX_WSA_CALL1("CloseHandle", CloseHandle, port);
+ } while ((ret < 0) && (__threadErrno == EINTR));
+ CloseHandle(port);
+# endif
+ }
+# else /* !DO_WRAP_CALLS */
+
+ fclose(fp);
+# ifdef WIN32
+ CloseHandle(port);
+# endif
+
+# endif /* !DO_WRAP_CALLS */
+ }
+%}
+! !
+
+!SerialPort methodsFor:'low level'!
+
+baudRate:newRate
+%{
+ OBJ fp;
+
+ fp = __INST(filePointer);
+ if ((fp != nil) && __isSmallInteger(newRate)) {
+ SERIALPORT port;
+ int ret;
+
+ port = PORT_FROM_FILE_OBJECT(fp);
+#ifdef WIN32
+ {
+ DCB dcb;
+
+ ZeroMemory(&dcb, sizeof(dcb));
+ dcb.DCBlength = sizeof(dcb);
+ GetCommState(port, &dcb);
+
+ dcb.BaudRate = __intVal(newRate);
+
+ if (! SetCommState(port, &dcb)) {
+ RETURN(false);
+ }
+ RETURN(true);
+ }
+# else /* ! WIN32 */
+ /* add code for unix ioctl here ... */
+# endif /* WIN32 */
+ }
+%}.
+ self primitiveFailed.
+! !
+
+!SerialPort methodsFor:'printing & storing'!
+
+printOn:aStream
+ aStream nextPutAll:'SerialPort(baudRate='.
+ baudRate printOn:aStream.
+ aStream nextPutAll:')'.
+! !
+
+!SerialPort methodsFor:'queries'!
+
+getName
+ "return the name; here, we return the devices name"
+
+ ^ portName
+! !
+
+!SerialPort methodsFor:'opening'!
+
+open
+ |errorNumber|
+
+ filePointer notNil ifTrue:[
+ ^ self errorAlreadyOpen
+ ].
+%{
+ FILE *fp;
+ SERIALPORT port;
+ char *__portName;
+ int __setBaudRate = 1,
+ __setDataBits = 1,
+ __setXOnChar = 1,
+ __setXOffChar = 1,
+ __setInFlowCtrl = 1,
+ __setOutFlowCtrl = 1,
+ __setStopBits = 1,
+ __setParityType = 1;
+ int __baudRate, __dataBits;
+ int __xOnChar, __xOffChar;
+ int __inFlowCtrl, __outFlowCtrl;
+ int __stopBits, __parityType;
+#ifdef WIN32
+ COMMTIMEOUTS timeouts;
+ DCB dcb;
+#endif /* WIN32 */
+
+# define XONOFF 1
+# define HARDWARE 2
+# define STOP1 1
+# define STOP2 2
+# define STOP1_5 3
+# define ODD 1
+# define EVEN 2
+# define NONE 3
+
+ if (__isString(__INST(portName))) {
+ __portName = __stringVal(__INST(portName));
+ } else {
+ goto failure;
+ }
+
+ if (__isSmallInteger(__INST(baudRate))) {
+ __baudRate = __intVal(__INST(baudRate));
+ } else if (__INST(baudRate) == nil) {
+ __setBaudRate = 0;
+ } else {
+ goto failure;
+ }
+
+ if (__isSmallInteger(__INST(dataBits))) {
+ __dataBits = __intVal(__INST(dataBits));
+ } else if (__INST(dataBits == nil)) {
+ __setDataBits = 0;
+ } else {
+ goto failure;
+ }
+
+ if (__isSmallInteger(__INST(xOnChar))) {
+ __xOnChar = __intVal(__INST(xOnChar));
+ } else if (__isCharacter(__INST(xOnChar))) {
+ __xOnChar = __intVal(_characterVal(__INST(xOnChar)));
+ } else if (__INST(xOnChar) == nil) {
+ __setXOnChar = 0;
+ } else {
+ goto failure;
+ }
+
+ if (__isSmallInteger(__INST(xOffChar))) {
+ __xOffChar = __intVal(__INST(xOffChar));
+ } else if (__isCharacter(__INST(xOffChar))) {
+ __xOffChar = __intVal(__characterVal(__INST(xOffChar)));
+ } else if (__INST(xOffChar) == nil) {
+ __setXOffChar = 0;
+ } else {
+ goto failure;
+ }
+
+ if (__INST(inFlowCtrlType) == @symbol(xOnOff)) {
+ __inFlowCtrl = XONOFF;
+ } else if (__INST(inFlowCtrlType) == @symbol(hardware)) {
+ __inFlowCtrl = HARDWARE;
+ } else if (__INST(inFlowCtrlType) == nil) {
+ __setInFlowCtrl = 0;
+ } else {
+ goto failure;
+ }
+
+ if (__INST(outFlowCtrlType) == @symbol(xOnOff)) {
+ __outFlowCtrl = XONOFF;
+ } else if (__INST(outFlowCtrlType) == @symbol(hardware)) {
+ __outFlowCtrl = HARDWARE;
+ } else if (__INST(outFlowCtrlType) == nil) {
+ __setOutFlowCtrl = 0;
+ } else {
+ goto failure;
+ }
+
+ if (__INST(stopBitsType) == @symbol(stop1)) {
+ __stopBits = STOP1;
+ } else if (__INST(stopBitsType) == @symbol(stop2)) {
+ __stopBits = STOP2;
+ } else if (__INST(stopBitsType) == @symbol(stop1_5)) {
+ __stopBits = STOP1_5;
+ } else if (__INST(stopBitsType) == nil) {
+ __setStopBits = 0;
+ } else {
+ goto failure;
+ }
+
+#ifdef WIN32
+ port = CreateFile(__portName,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, /* comm devices must be opened with exclusive access */
+ NULL, /* no security attrs */
+ OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
+ 0, /* no overlapped I/O */
+ NULL /* hTemplate must be NULL for comm devices */
+ );
+
+ if (port == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "Win32OS [info]: serial port open failed\n");
+ errorNumber = __mkSmallInteger( __WIN32_ERR(GetLastError()) );
+ goto failure;
+ }
+
+ /* Flush the driver */
+ PurgeComm( port, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
+
+ /* Set driver buffer sizes */
+ SetupComm( port, 4096 /*SERIAL_IN_QUEUE_SIZE*/, 4096 /*SERIAL_OUT_QUEUE_SIZE*/);
+
+ /* Reset timeout constants */
+ timeouts.ReadIntervalTimeout= 0xFFFFFFFF;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = 0;
+ timeouts.WriteTotalTimeoutMultiplier = 0;
+ timeouts.WriteTotalTimeoutConstant = 0;
+ SetCommTimeouts( port, &timeouts );
+
+ /* Set communication parameters */
+ ZeroMemory(&dcb, sizeof(dcb));
+ dcb.DCBlength = sizeof(dcb);
+ GetCommState(port, &dcb);
+
+ if (__setBaudRate) dcb.BaudRate = __baudRate;
+ if (__setDataBits) dcb.ByteSize = __dataBits;
+ if (__setXOnChar) dcb.XonChar = __xOnChar;
+ if (__setXOffChar) dcb.XoffChar = __xOffChar;
+
+ if (__setStopBits) {
+ /* set stop bits */
+ switch(__stopBits) {
+ case STOP1_5: dcb.StopBits = 1; break; /* 1.5 stop bits */
+ case STOP1: dcb.StopBits = 0; break; /* 1 stop bit */
+ case STOP2: dcb.StopBits = 2; break; /* 2 stop bits */
+ default: goto errExit;
+ }
+ }
+
+ if (__setParityType) {
+ /* set parity */
+ switch(__parityType) {
+ case NONE: dcb.Parity = NOPARITY; break;
+ case ODD: dcb.Parity = ODDPARITY; break;
+ case EVEN: dcb.Parity = EVENPARITY; break;
+ default: goto errExit;
+ }
+ }
+
+ if (__setInFlowCtrl) {
+ /* set control flow */
+ dcb.fInX = FALSE;
+ dcb.fDtrControl = FALSE;
+ if (__inFlowCtrl == XONOFF) dcb.fInX = TRUE; /* XOn/XOff handshaking */
+ if (__inFlowCtrl == HARDWARE) dcb.fDtrControl = TRUE; /* hardware handshaking */
+ }
+ if (__setOutFlowCtrl) {
+ dcb.fOutX = FALSE;
+ dcb.fOutxCtsFlow = FALSE;
+
+ if (__outFlowCtrl == XONOFF) dcb.fOutX = TRUE; /* XOn/XOff handshaking */
+ if (__outFlowCtrl == HARDWARE) dcb.fOutxCtsFlow = TRUE; /* hardware handshaking */
+ }
+
+ if (! SetCommState(port, &dcb)) {
+ fprintf(stderr, "Win32OS [info]: serial port comm-setup failed\n");
+ errorNumber = __mkSmallInteger( __WIN32_ERR(GetLastError()) );
+ goto errExit;
+ }
+# endif /* WIN32 */
+
+ /*
+ * make it a FILE *
+ */
+# ifdef WIN32
+ {
+ int _fd = _open_osfhandle(port, 0);
+ fp = fdopen(_fd, "r+");
+ }
+# else
+ fp = fdopen(port, "r+");
+# endif
+ if (! fp) {
+ errorNumber = __MKSMALLINT(errno);
+ goto errExit;
+ }
+
+ {
+ OBJ t;
+
+ t = __MKOBJ(fp);
+ __INST(filePointer) = t;
+ __STORE(self, t);
+ }
+
+ RETURN( true );
+
+errExit: ;
+ CloseHandle(port);
+
+failure: ;
+# undef XONOFF
+# undef HARDWARE
+# undef STOP1
+# undef STOP2
+# undef STOP1_5
+# undef ODD
+# undef EVEN
+# undef NONE
+
+%}.
+ "all ok?"
+ filePointer notNil ifTrue:[
+ Lobby register:self.
+ ] ifFalse:[
+ errorNumber isNil ifTrue:[
+ self error:'invalid argument(s)'.
+ ] ifFalse:[
+ (OperatingSystem errorHolderForNumber:errorNumber) reportError
+ ].
+ ].
+! !
+
+!SerialPort class methodsFor:'documentation'!
+
+version
+ ^ '$Header: /cvs/stx/stx/libbasic2/SerialPort.st,v 1.1 2006-02-02 16:22:51 cg Exp $'
+! !