Library Documentation, Copyright ã 1993 Looking Glass Design, Inc.
LGDCommunicationKit Release 1.0 (prerelease)
Project Manager:  Paul Girone
Written by: Mike Gobbi, June 24/1993 (11:50 am)
$Revision: 1.3 $

LGDBasicPortProtocol

Adopted By:	LGDSerialPort

Declared In:	LGDBasicPortProtocol.h

Protocol Description

The LGDBasicPortProtocol defines the minimum functionality required by the objects in the LGDCommunicationKit that utilize serial port objects.  The LGDSerialPort class conforms to this protocol, as (implicitly) does its subclass the LGDAppSerialPort class.  Thus, these two objects are suitable for use with the LGDChat and LGDCreditCardAuthorization classes.

Method failure

If no port is open, then the methods which set configuration flags may either return nil, or may return self and store the flags and apply them when the port is actually opened ± this protocol does not specify what behaviour will occur.  It is only guaranteed that ports may be configured after they have been opened.

This protocol declares no method for returning error codes, so all that may be discovered is that a call failed ªfor some reasonº.  Most unix calls to modify the serial port will set the global variable errno (declared in <errno.h>), and this should be checked if any method fails.  If the error code is zero, then the error occured before any low-level unix calls were made.

To use the LGDChat and LGDCreditCardAuthorization objects, you must supply them with a suitable serial port object.  There are three ways to go about doing this.

Using a subclass of LGDSerialPort

Since the LGDSerialPort class conforms to this protocol, its subclass LGDAppSerialPort also conforms, as will any other subclasses.  This is by far the easiest way to get serial port functionality.

Subclassing an existing serial port object

There are a number of serial port objects available which provide the functionality required by the higher-level classes of the LGDCommunicationKit.  Unfortunately, the method names and arguments required vary widely from one class to another.

A subclass of such a non-conforming class can be created which conforms to the protocol.  For instance, if the class MysteryPort does not conform to the protocol, the subclass

		@interface ConformingMysteryPort:MysteryPort
		<LGDBasicPortProtocol>
		{
			...
		}
		
		...
		
		@end

could be created that does conform.  This subclass will contain methods which simply translate the protocol message into one that the superclass can understand.  If the superclass used the methods lockDevice: and openDevice: to connect to a serial device, and could only be used in RAW mode, then the method

		- openAndLockDevice:(const char *)device
		  mode:(int)mode 
		  timeout:(long)seconds
		{
			// timeouts are ignored
			if (mode!=LGD_SP_RAW) goto error;
			if (![super openDevice:device]) goto error;
			if (![super lockDevice:device]) goto error;
			return self;
			
		error:
			return nil;
		}

could be used to conform the openAndLockDevice:mode:timeout: method.

Writing a conforming serial port class from scratch

This is by far the most difficult way to obtain a serial port object suitable for use with the higher-level classes in the LGDCommunicationKit, and should only be attempted by the brave.  A thorough reading of the protocol method descriptions should give enough information about the functionality that they must provide for a skilled programmer to create a suitable class.

Method Types

Connecting	- isDeviceAvailable:
	- openAndLockDevice:mode:timeout:
	- unlockAndClose
	- isOpen

Configuring	- setDiscipline:
	- setBaudRate:
	- setParity:
	- setCRMassage:
	- setDuplex:
	- setMode:
	- discipline
	- baudRate
	- parity
	- CRMassage
	- mode

Signals	- raiseBreak
	- lowerBreak
	- raiseDTR
	- lowerDTR
	- pause
	- continue

Communication	- dataAvailable
	- sendBlock:size:all:
	- getBlock:size:all:
	- flushInput
	- flushOutput

Instance Methods

CRMassage
- (BOOL)CRMassage

Returns whether or not input carriage returns will be turned into newlines and output/echoed newlines will be turned a carriage return followed by a linefeed.  If the serial port is in RAW mode, then this flag is ignored and no massaging occurs.

See also:  - setCRMassage:

baudRate
- (int)baudRate

Returns the current baud rate (this is an enumerated type, not the baud rate itself).

See also:  - setBaudRate:

continue
- continue

Sends a XON signal to the serial port.  This is used to restart data transmission after it was stopped using the XOFF signal.  Returns self if successful, and nil otherwise.

See also:  - pause

dataAvailable
- (BOOL)dataAvailable

Returns whether or not data is available to be read from the serial port.  If there is an error (the most common of which is that no port has been opened), then this method returns NO.

See also:  - readBlock:size:all:

discipline
- (int)discipline

Returns the current line discipline (LGD_SP_OLD or LGD_SP_NEW).

See also:  - setDiscipline:

flushInput
- flushInput

Discards all characters waiting to be read from the serial port.  Returns self if successful, and nil otherwise.

See also:  - flushOutput

flushOutput
- flushOutput

Discards all characters waiting to be written to the device.  Returns self if successful, and nil otherwise.

See also:  - flushInput

getBlock:size:all:
- (int)getBlock:(char *)buffer size:(int)bufSize all:(BOOL)yn

Reads at most bufSize characters from the serial device and stores them in buffer.  Returns the number of characters read, or -1 if there was an error which prevented the read from taking place (device not open, etc.).

If the ªallº flag is YES, then the call will not return until bufSize characters have been read or there has been an error.

Note that a return value of less than bufSize can have two meanings ± that there was an error, or there were no more characters to read and the all flag was NO.  Checking the global errno (declared in <errno.h>) is recommended if this returns a value not equal to bufSize.

See also:  - sendBlock:size:all:

isDeviceAvailable:
- (BOOL)isDeviceAvailable:(const char *)device

Returns whether there is a lock on device.  Even if there is no explicit lock set, an attempt to open the device may still fail if the device has been opened without being locked, or if another device which uses the same serial port is open.  More rarely, there may have been a race condition such that another process has locked and opened the device between the calls to isDeviceAvailable: and openAndLockDevice:mode:timeout:.  See openAndLockDevice:mode:timeout: for a list of available devices.

See also:  - openAndLockDevice:mode:timeout:

isOpen
- (BOOL)isOpen

Returns whether the reciever has opened its device.

See also:  - openAndLockDevice:mode:timeout:

lowerBreak
- lowerBreak

Lowers the BREAK line of the serial port.  Returns self if successful, and nil otherwise.

See also:  - raiseBreak

lowerDTR
- lowerDTR

Lowers the DTR (data terminal ready) line of the serial port.  Returns self if successful, and nil otherwise.

See also:  - raiseDTR

mode
- (int)mode

Returns the current mode of the reciever.  This mode will be one of
		LGD_SP_RAW
		LGD_SP_CBREAK
		LGD_SP_COOKED
Raw mode is used when binary data is to be transmitted, and cooked mode when performing interactive ASCII operations.  Cbreak mode is seldom used.

See also:  - setMode, - openAndLockDevice:mode:timeout:

openAndLockDevice:mode:timeout:
- openAndLockDevice:(const char *)device
mode:(int)mode
timeout:(long)seconds

Device is opened for reading and writing using mode mode and then locked.  Returns self if the device was opened within the interval specified by unlockAndClose
- unlockAndClose

This method is the standard way to stop using a serial device.  It closes the port, unlocks the device.  The current device is not changed.  Returns self if successful, and nil otherwise.

See also:  - close, - unlock, - setDevice:, - openAndLockDevice:mode:timeout:

 (no timeout if negative), and nil otherwise.

The commonly used devices are
	ttya	ttyb	Used for incoming connections from directly connected terminals without flow control.
	ttyfa	ttyfb	Used for incoming connections from directly connected terminals with flow control.
	ttyda	ttydb	Used for incoming connections from modems.
	ttydfa	ttydfb	Used by systems whose hardware supports RTS/CTS flow control (68040 and later) for incoming connections from modems.
	cua	cub	Used for outgoing connections to modems.
	cufa	cufb	Used by systems whose hardware supports RTS/CTS flow control (68040 and later) for outgoing connections to modems.

The available modes are
		LGD_SP_RAW
		LGD_SP_CBREAK
		LGD_SP_COOKED

In RAW mode, no input or output processing is done ± the characters are made available to the process connected through the device as soon as they are sent, and characters sent by the foreign process are immediately available.  Carriage-return massage does not take place in RAW mode.  This is the mode generally used for raw data transfer.

In CBREAK mode, flow control and interrupt processing take place, but non-control characters are made immediately available to the foreign process.

In COOKED mode (the mode terminals generally operate under), data is collected, but not sent to the process on the other end of the device until a newline is sent.

See also:  - unlockAndClose, - isOpen

parity
- (int)parity

Returns the current parity used to communicate with the serial port.  The parity will be one of
		LGD_SP_EVENPARITY
		LGD_SP_ODDPARITY
		LGD_SP_ZEROPARITY
		LGD_SP_NOPARITY

See also:  - setParity:

pause
- pause

Sends a XOFF signal to the device, signalling the hardware on the other end of the serial line to stop sending data until a XON signal is sent.  Returns self if successful, and nil otherwise.

See also:  - continue

raiseBreak
- raiseBreak

Raises the BREAK line on the serial port.  Returns self if successful, nil if unsuccessful.

See also:  - lowerBreak

raiseDTR
- raiseDTR

Raises the DTR (data terminal ready) line of the serial port.  Returns self if successful, and nil if unsuccessful.

See also:  - lowerDTR

sendBlock:size:all:
- (int)sendBlock:(const char *)buffer size:(int)size all:(BOOL)yn

Attempts to write bufSize characters from buffer to the serial port.  Returns the number of characters written, or -1 if there was an error which prevented any characters from being written.

If the all flag is YES, then the call will not return until bufSize characters have been written or there has been an error.

Note that a return value of less than bufSize can have two meanings ± that there was an error, or that the device signalled that it could accept no more characters and the all flag was NO.  Therefore it is strongly recommended that the global variable errno (declared in <errno.h>) be checked if there this method returns a value not equal to bufSize.

See also:  - getBlock:size:all:

setBaudRate:
- setBaudRate:(int)rate

Sets the baud rate used by the serial port.  Rate must be one of
		LGD_SP_B0
		LGD_SP_B50
		LGD_SP_B75
		LGD_SP_B110
		LGD_SP_B134
		LGD_SP_B150
		LGD_SP_B200
		LGD_SP_B300
		LGD_SP_B600
		LGD_SP_B1200
		LGD_SP_B1800
		LGD_SP_B2400
		LGD_SP_B4800
		LGD_SP_B9600
Returns self if successful, nil if unsuccessful.

See also:  - baudRate

setCRMassage:
- setCRMassage:(BOOL)yn

Determines whether or not input carriage returns will be turned into newlines and output and echoed newlines will be turned a carriage return followed by a linefeed.  In RAW mode, this flag is ignored and no massaging takes place.  Returns self if successful, nil if unsuccessful.

See also:  - CRMassage

setDiscipline:
- setDiscipline:(int)aDiscipline

Sets the line discipline to be one of
		LGD_SP_OLD
		LGD_SP_NEW
Returns self if successful, nil if unsuccessful.

See also:  - discipline

setDuplex:
- setDuplex:(int)duplex

Sets the serial port to be one of
		LGD_SP_HALFDUPLEX
		LGD_SP_FULLDUPLEX
In full-duplex mode, any characters sent to the serial device will also be echoed back as input.  Returns self if successful, nil if unsuccessful.

See also:  - duplex

setMode:
- setMode:(int)mode

Sets the mode of the serial port to one of
		LGD_SP_RAW
		LGD_SP_CBREAK
		LGD_SP_COOKED
Returns self if successful, nil if unsuccessful.

See also:  - mode, - openAndLockDevice:mode:timeout:

setParity:
- setParity:(int)parity

Sets the parity of the serial device to be one of
		LGD_SP_EVENPARITY
		LGD_SP_ODDPARITY
		LGD_SP_ZEROPARITY
		LGD_SP_NOPARITY
In zero parity and no parity modes, characters are accepted regardless of the parity bit, but are sent out with the parity bit either cleared (zero parity) or set (no parity).  Returns self if successful, nil if unsuccessful.

See also:  - parity

unlockAndClose
- unlockAndClose

Closes the port and unlocks the device.  Returns self if successful, and nil otherwise.

See also:  - isClosed, - openAndLockDevice:mode:timeout:

Constants and Defined Types

// Disciplines
// (Referenced definitions found in <sgtty.h>)
#define LGD_SP_NEW	NTTYDISC
#define LGD_SP_OLD	OTTYDISC

// Modes
#define LGD_SP_RAW		0
#define LGD_SP_CBREAK		1
#define LGD_SP_COOKED		2

// Speeds
// (Referenced definitions found in <sgtty.h>)
#define LGD_SP_B0		B0
#define LGD_SP_B50		B50
#define LGD_SP_B75		B75
#define LGD_SP_B110		B110
#define LGD_SP_B134		B134
#define LGD_SP_B150		B150
#define LGD_SP_B200		B200
#define LGD_SP_B300		B300
#define LGD_SP_B600		B600
#define LGD_SP_B1200		B1200
#define LGD_SP_B1800		B1800
#define LGD_SP_B2400		B2400
#define LGD_SP_B4800		B4800
#define LGD_SP_B9600		B9600

// Parity
// (Referenced definitions found in <sgtty.h>)
#define LGD_SP_EVENPARITY	EVENP
#define LGD_SP_ODDPARITY	ODDP
#define LGD_SP_ZEROPARITY	0
#define LGD_SP_NOPARITY	(EVENP|ODDP)

// Duplex
#define LGD_SP_HALFDUPLEX	0
#define LGD_SP_FULLDUPLEX	1