/*
 
PrivL0serial.h
 
*/
 
#ifndef PRIVL0SERIAL_H
#define PRIVL0SERIAL_H
 
#include <NET\L0Serial.h>
 
/* 
 * universal multiplayer library level 0 header file
 * transport layer: serial PC-windows 95
 */
 
#if !defined(__L0SERIALPCWIN95_TYPES__)
#define __L0SERIALPCWIN95_TYPES__
 
#if !defined(ONLY_TYPES)
#define L0SERIALPCWIN95_UNDEF
#define ONLY_TYPES
#endif /* !ONLY_TYPES */
 
/*
 * include here any other include files you need
 */
#include <windows.h>
 
#include "L0GlDef.h"
 
 
#if defined(L0SERIALPCWIN95_UNDEF)
#undef ONLY_TYPES
#undef L0SERIALPCWIN95_UNDEF
#endif /* !L0SERIALPCWIN95_UNDEF */
 
/* 
 * number of bytes the buffer must be able to store between two
 * consecutive calls to the net engine. a 1Kb value enables to call
 * the engine about every 5 frames with a continuous flow of data
 * at 115Kbps.
 */
#define C_uwMaxAsyncLength 1024
 
M_BeginDeclareEnumerate(tdeNetL0PCWin95SerialBaudStatus)
E_Net_L0SerialBaud_Default,
E_Net_L0SerialBaud_Set,
E_Net_L0SerialBaud_Ok,
E_Net_L0SerialBaud_Invalid
 
M_EndDeclareEnumerate(tdeNetL0PCWin95SerialBaudStatus, unsigned char)
 
/* length of send buffer */
/* should correspond to the amount of data that can be sent between two calls to vNetEngine */
 
#define C_usSerialBufferSize ((unsigned short)300)
 
/* 
 * template name for all structures
 */
 
/*
 * structures of transmission data blocks 
 */
 
/* number of useful bytes in a send slot */
#define BLOCKSIZE 30
 
/* identifier for invalid slot */
#define INVALID_SLOT ((unsigned char)-1)
 
/* byte used to mark the beginning of packets */
#define STARTMARK 0xa3
 
/* structure of the data packets sent over the line */
 
#pragma pack(push)
#pragma pack(1)
 
typedef struct {
    unsigned char ucStartMark;  /* mark the beginning of the packet */
    unsigned short usChecksum;  /* redundancy checksum */
    unsigned char ucSeqn;       /* sequence number */
    unsigned char ucAckn;       /* acknowledgement sequence number */
    unsigned char ucSize;       /* number of meaningful bytes in the packet */
    char acData[BLOCKSIZE];     /* data to transmit */
} tdstPacket;
 
#pragma pack(pop)
 
/* slots used to store packets to send and received packets */
typedef struct {
    unsigned long ulDate;       /* date of send request / date of reception */
    unsigned char ucSeqn;       /* sequence number */
    unsigned char ucState;      /* state of slot */
    unsigned char ucSize;       /* number of meaningful bytes acData */
    char acData[BLOCKSIZE];     /* content of the packet */
} tdstSlot;
 
/* slot state */
typedef enum {
    FREE,                       /* slot not used */
    TO_SEND,                    /* slot waiting to be sent */
    SENT,                       /* slot sent not yet acknowledged */
    TIMED_OUT,                  /* slot sent, not acknowledged, whose timer has timed out */
    ACK,                        /* slot sent and acknowledged / slot received and acknowledged */
    RECVD                       /* slot received, not yet acknowledged */
} tdeState;
 
/* array of slots */
typedef struct {
  tdstSlot *pstSlot;            /* array of slots*/
  int iSize;                    /* number of elements in the array */
  unsigned long ulTimeout;      /* limit to consider when computing the timeout of the slots of the array */
} tdstWindow;
 
/*
 * link buffer structure
 */
 
 enum { eLinkOk, eLinkFull, eLinkEmpty }; /* error codes */
 
/* size of each link */
#define LINKSIZE BLOCKSIZE
 
/* link structure */
typedef struct {
  unsigned char ucSeqN;         /* sequence number */
  unsigned char ucSize;         /* number of meaningful bytes in acData */
  int iNextIndex;               /* index of next link in the list */
  char acData[LINKSIZE];        /* content */
} tdstLink;
 
/* list of links */
typedef struct {
  int iNLinks;                          /* total number of links */
  unsigned char ucAwaitedSeqN;          /* lowest sequence number not received yet */
  int iHead;                            /* index of first link in the list */
  int iFirstSequence;                   /* number of links in sequence starting from the head of the list */
  int iNFreeLinks;                      /* number of links not used in the list */
  unsigned long ulFirstSequenceLength;  /* total number of meaningful bytes in the first sequence of links */
  tdstLink *pstLink;                    /* array of links */
} tdstLinkBuffer;
 
 
 
/*
 * ring buffer structure
 */
 
/* number of bytes in the ring */
#define RINGBUFFERSIZE C_usSerialBufferSize
 
typedef struct {
    char acBuffer[RINGBUFFERSIZE];      /* content of the ring */
    unsigned long ulLowMark;            /* index of the first meaningful byte in acBuffer */
    unsigned long ulHighMark;           /* index of the last  meaningful byte in acBuffer */
    
    char *pcBigMsg;             /* pointer to a 'big' message */
    unsigned long ulSize;       /* length of the big message  */
    unsigned long ulBottom;     /* index of first byte of pcBigMsg not sent yet */
} tdstRingBuffer;
 
enum { eRingOk, eRingBigOk, eRingFull, eRingEmpty }; /* error codes */
 
/* low level functions used by both l0serial.c and l0modem.c */
 
void vInitWindow(tdstWindow *, int, unsigned long);
void vDeleteWindow(tdstWindow *);
void vInitLinkBuffer(tdstLinkBuffer *, int iNLinks);
void vDeleteLinkBuffer(tdstLinkBuffer *);
void vInitRingBuffer(tdstRingBuffer *);
 
void vAddThreadClient(tduwNetChannel);
void vRemoveThreadClient(tduwNetChannel);
 
/*
 * channel structure
 */
 
typedef struct tdstL0PCWin95SerialChannel_
{
 /* internal error status in case of transport layer faults */
 tdeNetTransferStatus eChannelStatus;
 
 /* number of bytes received for the currently incoming data */
 unsigned long ulBytesInReadBuffer;
 
 /* pointers to I/O buffers */
 tdpPointer pCurrentReceivingBuffer;
 
 /* message being received, and associated input point */
 tdpPointer pCurrentReceivedMessage;
 tdpPointer pCurrentMessageIncomingPoint;
 /* number of bytes to read before the message is completely here */
 unsigned long ulBytesToCompleteIncomingMessage;
 
 /* is an I/O operation in progress ? */
 unsigned char ubf1ReadInProgress : 1;
 unsigned char ubf1WriteInProgress : 1;
 
 /* can this channel be used to send broadcast messages ? */
 unsigned char ubf1IsBroadcast : 1;
 
 /* is this slot in use in the protocol's array of channels ? */
 unsigned char ubf1IsSlotInUse : 1;
 
 /* is this slot to be considered by the serial layer or by the modem layer ? */
 unsigned char ubf1IsSlotForModem : 1;
 
 /* is this slot connected to a remote end ? (useful for modem connections) */
 unsigned char ubf1IsSlotConnected : 1;
 
 /* has this slot its final baud rate*/
 tdeNetL0PCWin95SerialBaudStatus eBaudStatus;
 /* Max baud rate*/
 unsigned long ulMaxBaudRate;
 
 /*
  * fields related to threaded sending system
  */
 
 /* handle on a file opened on the serial port */
 HANDLE hCom;
 
 /* device's status */
 DCB stChannelStatus;
 
 tdstWindow stSendWindow; /* array of blocks to send */
 tdstWindow stRecvWindow; /* array of blocks to receive */
 
 tdstPacket stPacket;          /* buffer for send operation */
 
 unsigned char ucSeqn;         /* next block sequence number */
 
 OVERLAPPED stOverlappedRead;
 
 OVERLAPPED stOverlappedWrite;
 
 char acReadBuffer[sizeof(tdstPacket)*2]; /* buffer for ReadFile*/
 unsigned long ulReadPos;   /* where to store bytes in the previous buffer */
 
 tdstRingBuffer stSendBuffer; /* where blocks to send are taken from */
 tdstLinkBuffer stRecvBuffer; /* where incoming blocks are reassembled */
 
 HANDLE hBufferEmpty; /* event used to signal when the send buffer is empty */
 HANDLE hSlotsEmpty; /* event used to signal when the send slots have all been sent and acknowledged */
 
 CRITICAL_SECTION stSendBufferAccess; /* mutual exclusion on stSendBuffer */
 CRITICAL_SECTION stRecvBufferAccess; /* mutual exclusion on stRecvBuffer */
 CRITICAL_SECTION stChannelAccess; /* mutual exclusion on channel */
} tdstL0PCWin95SerialChannel;
 
 
#endif /* !__L0SERIALPCWIN95_TYPES__ */
 
#if !defined(ONLY_TYPES)
 
#if !defined(__L0SERIALPCWIN95_VARS__)
#define __L0SERIALPCWIN95_VARS__
 
#undef EXTERN
#undef extern
#if !defined(GLOBALS)
#define EXTERN extern
#else /* !GLOBALS */
#define EXTERN
#endif /* !GLOBALS */
 
/*
 * variables of the above types are here. declarations with initialization
 * are of the form:
 *
 * <type> <variable name>
 * #if defined(GLOBALS)
 * = <initial values>
 * #endif
 * ;
 */
 
#endif /* !__L0SERIALPCWIN95_VARS__ */
 
#if !defined (__L0SERIALPCWIN95_PROTOS__)
#define __L0SERIALPCWIN95_PROTOS__
 
/*
 Prototypes :
*/
tduwNetChannel uwL0PCWin95SerialStartChannelScan(void);
tduwNetChannel uwL0PCWin95SerialNextChannel(tduwNetChannel);
tduwNetChannel uwL0PCWin95SerialStartBroadcastChannelScan(void);
tduwNetChannel uwL0PCWin95SerialNextBroadcastChannel(tduwNetChannel);
NetLib_tdeErrorStatus eL0PCWin95SerialReadData(tduwNetChannel*,tdpPointer*);
NetLib_tdeErrorStatus eL0PCWin95SerialSendData(tduwNetChannel,tdpPointer);
NetLib_tdeErrorStatus eL0PCWin95SerialQueryChannelStatus(tduwNetChannel);
void vL0PCWin95SerialNetEngine(void);
void vL0PCWin95SerialCloseChannel(tduwNetChannel);
void vL0PCWin95SerialCloseProtocol(void);
 
NetLib_tdeErrorStatus eL0PCWin95SerialPurgeChannel(tduwNetChannel);
NetLib_tdeErrorStatus eL0PCWin95SerialFlushChannel(tduwNetChannel);
NetLib_tdeErrorStatus eL0PCWin95SerialResetChannel(tduwNetChannel);
#endif /* !__L0SERIALPCWIN95_PROTOS__ */
 
#endif /* !ONLY_TYPES */
 
#endif /* PRIVL0SERIAL_H */
