#include "serial_mac.h" #include "stdio.h" // Much of this code is from an example in NIM Devices 7-12. /*Open a serial port for activity*/ SerialID Serial_OpenPort(long baud,long parity, long char_bits, long stop_bits) { short err,err2; SerialID port; port.bufHandle=NULL; // Always open the output driver first err=OpenDriver("\p.AOut",&port.out); err2=OpenDriver("\p.AIn",&port.in); // Maybe the driver was already open... be cruel, close it down and reopen // Evil if someone else was using it.. // Should also be checking for the specific err code that means its open, but we're lazy. if (err || err2) { // Always pass KilIO() the output driver, not the input. It handles both... KillIO(port.out); // CloseDriver() waits for pending IO, fortunately we killed any... CloseDriver(port.out); CloseDriver(port.in); // Ok now open them again err=OpenDriver("\p.AOut",&port.out); err2=OpenDriver("\p.AIn",&port.in); } if (err==noErr && err2==noErr) { // Always do SerReset() only on the output driver err=SerReset(port.out,baud+parity+char_bits+stop_bits); // Set a larger input buffer so we dont drop stuff port.bufHandle = NewHandle(kInputBufSize); HLock(port.bufHandle); SerSetBuf(port.in,*port.bufHandle,kInputBufSize); // Set up serial handshaking, on output only SerShk myShake; myShake.fXOn =0; // xon/xoff ouput flow control myShake.fCTS =0; // CTS/DTR flow control myShake.errs =0; //error mask myShake.evts =0; //event mask myShake.fInX =0; //xon/xoff input flow control myShake.fDTR =0; // DTR input flow control // Use control call 14 instead of SerHShake function because it // allows control of DTR err = Control(port.out, 14, &myShake); } return port; } /*Read all available input without blocking. Returns chars read. */ /*Reads at most length characters*/ int Serial_Read(SerialID port, char* buf, int length) { long count=0; IOParam myparam; // Check how many bytes are available SerGetBuf(port.in,&count); // Dont bloc, so if there arent enough bytes avail, then ask for only // whats there if (count0) { myparam.ioRefNum = port.in; // output driver myparam.ioBuffer = buf; // pointer to data myparam.ioReqCount = length; // number of bytes to read myparam.ioCompletion = NULL; // no completion routine myparam.ioVRefNum = 0; // not used by serial driver myparam.ioPosMode =0; // not used by serial driver PBRead((ParmBlkPtr)&myparam,FALSE); } // return the bytes actually read return length; } /*Read all input, but block waiting for at least something.*/ int Serial_ReadBlocking(SerialID port, char* buf, int length) { return 0; } /*Write length chars from buf*/ int Serial_Write(SerialID port, char* buf, int length) { IOParam myparam; myparam.ioRefNum = port.out; // output driver myparam.ioBuffer = buf; // pointer to data myparam.ioReqCount = length; // number of bytes to send myparam.ioCompletion = NULL; // no completion routine myparam.ioVRefNum = 0; // not used by serial driver myparam.ioPosMode =0; // not used by serial driver // Write synchronously PBWrite((ParmBlkPtr)&myparam, FALSE); return length; } /* Close the port */ int Serial_ClosePort(SerialID port) { // Restore the default input buffer by passing 0 length... but why do we pass our handle? SerSetBuf(port.in, *port.bufHandle, 0); // kill pending IO operations.. call this only on output or crash...! KillIO(port.out); // Close the drivers... CloseDriver(port.in); // Close input driver first CloseDriver(port.out); // Release the buffer memory if (port.bufHandle!=NULL) { HUnlock(port.bufHandle); DisposeHandle(port.bufHandle); port.bufHandle=NULL; } return 0; } /* Are their bytes waiting to be read? 0 indicates nothing waiting */ /* any other indicates minimum bytes waiting */ int Serial_BytesAvailable(SerialID port) { long count=0; SerGetBuf(port.in,&count); return count; } /* Flush the input queue */ int Serial_FlushInput(SerialID port) { return 0; }