#define ERROR (-1) /* don't change these 2 because they have to */ #define TIMEOUT (-2) /* be the same as the #defines in sz.c and rz.c */ #define SERBUFSIZE 1024L /* * Serial IO functions * * based on routines by A.Livshits & J.M.Forgeas * * Extensively modified for Amiga zmodem by Frank Harper */ #include #include #include #include #include #include #include #include #include #include #include #include "intuition/intuition.h" extern int Lleft; /* number of chars in input buffer */ extern UBYTE SerOpen; /* True if Serial port is open */ static UBYTE TimeOpen; extern struct IOExtSer *InSer, *OutSer; extern struct MsgPort *InSerPort, *OutSerPort; extern ULONG InSerSigMask, OutSerSigMask; /* Masks for Wait & WaitIO */ extern ULONG IOTimeSigMask; extern struct timerequest *IOTime; extern struct MsgPort *TimerPort; extern struct Window *Win; struct MsgPort *CreatePort(); void *CreateExtIO(),*AllocMem(); static UBYTE RecSerBuf[SERBUFSIZE]; /* Serial input buffer */ static UBYTE Previous=FALSE; /* True if asynchronous serial write is pending */ extern int Enable_Abort = 0; /* No ^C allowed (Manx) */ /* * Init. serial port * * bps: bits per second (or Baud rate) between 110 and 29,200 * if this parameter is -1 then the device is opened with * no changes in bps,len, or stop. * * len: lenght of each word sent and received (7 or 8) * stop: number of stop bits 1 or 2 * flags: used to set other parameters * * returns pointer to IOExtSer structure, so caller can determine what * the serial parameters in use actually are. In case of failure * return NULL. */ struct IOExtSer *SetSer(bps,len,stop,flags) ULONG bps,len,stop,flags; { if( bps!=-1 && (bps<110 || bps>29200 || len<7 || len>8 || stop<1 || stop>2)) return NULL; InSer = (struct IOExtSer *) AllocMem((long)sizeof(*InSer),MEMF_PUBLIC|MEMF_CLEAR); if(InSer==NULL) return NULL; OutSer = (struct IOExtSer *) AllocMem((long)sizeof(*OutSer),MEMF_PUBLIC|MEMF_CLEAR); if( OutSer==NULL) return NULL; InSerPort = InSer->IOSer.io_Message.mn_ReplyPort = CreatePort(0L,0L); if(InSerPort==NULL) return NULL; InSerSigMask = 1 << (InSerPort->mp_SigBit); InSer->io_SerFlags = SERF_SHARED&flags; if(OpenDevice(SERIALNAME,NULL,InSer,NULL)) { fprintf(stderr,"Error opening serial device\n"); return NULL; } if( bps!=-1 ) { InSer->io_SerFlags = flags; InSer->io_Baud = bps; InSer->io_ReadLen = InSer->io_WriteLen = len; InSer->io_StopBits = stop; InSer->io_CtlChar = 0x11130000L; InSer->io_RBufLen = SERBUFSIZE; InSer->io_BrkTime = 250000L; InSer->IOSer.io_Command = SDCMD_SETPARAMS; if( DoIO(InSer)!=0 ) { fprintf(stderr,"Error setting serial port parameters\n"); return NULL; } } CopyMem(InSer,OutSer,sizeof(struct IOExtSer)); OutSerPort = OutSer->IOSer.io_Message.mn_ReplyPort = CreatePort(0L,0L); if(OutSerPort==NULL) return NULL; OutSerSigMask = 1 << (OutSerPort->mp_SigBit); SerOpen=1; return InSer; } /* * Close serial port */ void CloseSer() { if(Previous) { Wait(OutSerSigMask); GetMsg(OutSerPort); } if(SerOpen) { CloseDevice(InSer); SerOpen=0; } if(OutSerPort) { DeletePort(OutSerPort); OutSerPort=NULL; } if(InSerPort) { DeletePort(InSerPort); InSerPort=NULL; } if(OutSer) { FreeMem(OutSer,(long)sizeof(*OutSer)); OutSer=NULL; } if(InSer) { FreeMem(InSer,(long)sizeof(*InSer)); InSer=NULL; } } /* * Write asynchronously the len characters (up to SERBUFSIZE) pointed * at by c. */ int LWriteSer(c,len) UBYTE *c; int len; { ULONG IntuiMask,mask; static UBYTE buf[SERBUFSIZE]; if (len==0) return (0); if (len > SERBUFSIZE || SerOpen==0) return ERROR; if (Previous) { IntuiMask = 1 << (Win->UserPort->mp_SigBit); mask = Wait(OutSerSigMask | IntuiMask); if ((mask & IntuiMask) && CheckQuit()) { KillIO( (struct IOStdReq *)OutSer,mask); Previous=FALSE; bibi(1); } GetMsg(OutSerPort); } Previous = TRUE; CopyMem(c,buf,len); OutSer->IOSer.io_Data = (APTR)buf; OutSer->IOSer.io_Length = (ULONG)len; OutSer->IOSer.io_Command = CMD_WRITE; SendIO(OutSer); return (0); } /* * Send an asynchronous read request for n characters * put result in buf */ SendSer(n,buf) int n; char *buf; { if( SerOpen==0 ) { fprintf(stderr,"Read attempt on closed Serial Port\n"); return ERROR; } InSer->IOSer.io_Data = (APTR)buf; InSer->IOSer.io_Length = n; InSer->IOSer.io_Command = CMD_READ; SendIO(InSer); return (0); } /* * Purge any characters waiting in serial port queue * */ PurgeSer() { if( SerOpen!=0 ) { InSer->IOSer.io_Command = CMD_CLEAR; if ( DoIO(InSer)!=0) fprintf(stderr,"can't purge serport\n"); } } /* * Initialize timer device */ int SetTimer() { int err; TimerPort = CreatePort(0,0); if (TimerPort==NULL) return ERROR; IOTimeSigMask = 1 << (TimerPort->mp_SigBit); IOTime = (struct timerequest *) CreateExtIO(TimerPort,sizeof(struct timerequest)); if (IOTime==NULL) return ERROR; if( (err=OpenDevice(TIMERNAME,UNIT_VBLANK,IOTime,0))!=0) TimeOpen=0; else TimeOpen=1; return err; } /* * Close timer device */ void CloseTimer() { if( TimeOpen ) { CloseDevice(IOTime); TimeOpen=0; } if(IOTime) { DeleteExtIO(IOTime,sizeof(struct timerequest)); IOTime=NULL; } if(TimerPort) { DeletePort(TimerPort); TimerPort=NULL; } } /* send a break to the host */ void SendBreak() { if ( SerOpen ) { InSer->IOSer.io_Command = SDCMD_BREAK; if( DoIO(InSer)!=0) fprintf(stderr,"SendBreak:error sending break\n"); } } /* * Read a character from serial port. Timeout is in tenths of seconds. * */ int ReadSer(timeout) int timeout; { int ch; ULONG mask,IntuiMask; static UBYTE *NextChar; int Quit; /* if(CheckQuit()) bibi(1);*/ if( !SerOpen) return ERROR; if( Lleft>0 ) { --Lleft; return (*NextChar++); } IOTime->tr_time.tv_secs = timeout/10; IOTime->tr_time.tv_micro = 100000*(timeout%10); IOTime->tr_node.io_Command = TR_ADDREQUEST; SendIO(IOTime); SendSer(1,RecSerBuf); IntuiMask = 1 << (Win->UserPort->mp_SigBit); mask=Wait( InSerSigMask | IOTimeSigMask | IntuiMask); if (CheckQuit()) { KillIO(IOTime,mask); KillIO( (struct IOStdReq *)InSer,mask); bibi(1); } else if ((mask&InSerSigMask)!=0) { KillIO(IOTime,mask); GetMsg(InSerPort); ch=RecSerBuf[0]; if( (Lleft=CharsWaiting())>0){/* find out how many characters are waiting */ InSer->IOSer.io_Data = (APTR)RecSerBuf; InSer->IOSer.io_Length = LleftIOSer.io_Command = CMD_READ; DoIO(InSer); NextChar=RecSerBuf; } return(ch); } else { /* it was the timer signal */ KillIO( (struct IOStdReq *)InSer,mask); WaitIO(IOTime); return TIMEOUT; } } /* * Determine the number of characters waiting in the serial.device * input buffer * */ CharsWaiting() { if( SerOpen ) { InSer->IOSer.io_Command = SDCMD_QUERY; if( DoIO(InSer)!=0) fprintf(stderr,"CharsWaiting: IO error\n"); return (int)(InSer->IOSer.io_Actual); } } /* * If IO isn't done Abort it * in any case GetMsg it * */ KillIO(Req,Mask) struct IOStdReq *Req; ULONG Mask; { ULONG SigMask; struct MsgPort *SigPort; SigPort=Req->io_Message.mn_ReplyPort; SigMask=1 << (SigPort->mp_SigBit); if( (Mask & SigMask)==0 ) { AbortIO(Req); Wait(SigMask); } GetMsg(SigPort); }