#ifndef __IRLAP_H
#define __IRLAP_H
#include "IrDATypes.h"
#include "IrStream.h"
#include "CBufferSegment.h"
#include "IrEvent.h"
class TIrGlue;
class TIrLMP;
class TIrQOS;
class TLSAPConn;
class TCMOSlowIRStats;
class CIrDiscovery;
class CIrDevice;
class CBuffer;
#define kIrLAPVersionNumber 0x00
#define kIrLAPBroadcastAddr 0x7F
#define kIrLAPCommandBit 0x01
#define kIrLAPBroadcastDevAddr 0xFFFFFFFF
#define kIrLAPSnifferDevAddr 0x736E6966
#define kIrLAPSniffeeDevAddr 0x726F7365
#define kIrLAPProbeDevAddr 0x70726265
#define kIrDefaultLeadinCount 10
#define kIrLAPFinalSlot 0xFF
enum IrLAPCommandsAndResponses
{
kIrLAPUSIMask = 0x03,
kIrLAPIMask = 0x01,
kIrLAPUnnumbered = 0x03,
kIrLAPSupervisory = 0x01,
kIrLAPInformation = 0x00,
kIrLAPPFMask = 0x10,
kIrLAPPollBit = 0x10,
kIrLAPFinalBit = 0x10,
kIrLAPNrMask = 0xE0,
kIrLAPNrShift = 5,
kIrLAPNsMask = 0x0E,
kIrLAPNsShift = 1,
kIrLAPUnexpectedNr = 0x01,
kIrLAPUnexpectedNs = 0x02,
kIrLAPInvalidNr = 0x04,
kIrLAPInvalidNs = 0x08,
kIrLAPCmdSNRM = 0x83,
kIrLAPCmdDISC = 0x43,
kIrLAPCmdUI = 0x03,
kIrLAPCmdXID = 0x2F,
kIrLAPCmdTEST = 0xE3,
kIrLAPRspRNRM = 0x83,
kIrLAPRspUA = 0x63,
kIrLAPRspFRMR = 0x87,
kIrLAPRspDM = 0x0F,
kIrLAPRspRD = 0x43,
kIrLAPRspUI = 0x03,
kIrLAPRspXID = 0xAF,
kIrLAPRspTEST = 0xE3,
kIrLAPFrameRR = 0x01,
kIrLAPFrameRNR = 0x05,
kIrLAPFrameREJ = 0x09,
kIrLAPFrameSREJ = 0x0D,
kIrLAPFrameINFO = 0x00
};
enum IrLAPFormatIdentifiers
{
kIrLAPDiscoveryXIDFormat = 0x01
};
enum IrLAPDiscoverFlags
{
kIrLAPDiscoverFlagsSlotMask = 0x03,
kIrLAPDiscoverFlags1Slot = 0x00,
kIrLAPDiscoverFlags6Slots = 0x01,
kIrLAPDiscoverFlags8Slots = 0x02,
kIrLAPDiscoverFlags16Slots = 0x03,
kIrLAPDiscoverFlagsNewAddr = 0x04
};
enum IrFRMRFlags {
kIrFRMRFlagUndefinedCtrl = 0x01,
kIrFRMRFlagInvalidIField = 0x02,
kIrFRMRFlagSizeExceeded = 0x04,
kIrFRMRFlagInvalidNrCount = 0x08,
kIrFRMRCrBit = 0x10
};
enum IrLAPStates
{
kIrLAPDisconnectedState,
kIrLAPQueryState,
kIrLAPConnectState,
kIrLAPListenState,
kIrLAPReplyState,
kIrLAPLastNDMState = kIrLAPReplyState,
kIrLAPPriReceiveState,
kIrLAPPriTransmitState,
kIrLAPPriCloseState,
kIrLAPSecReceiveState,
kIrLAPSecTransmitState,
kIrLAPSecCloseState
};
enum IrLAPTimings {
kIrMediaBusyTimeout = 600,
kIrDiscoverSlotTimeout = 100, kIrConnectFinalTimerTimeout = 500, kIrDisconnectWarningTimeout = 3 * 1000 };
enum IrLAPRetries
{
kMaxConnectRetries = 3,
kMaxDisconnectRetries = 3,
kMaxDiscoverRetries = 10 };
enum {
kMaxUnconnectedPacketSize = 64
};
#define kTXIDPacketSize 14 // Can't use sizeof because of padding stuff
class TXIDPacket
{
public:
UByte fPhonyBologna1; UByte fAddress;
UByte fCmdRsp;
UByte fFormatId;
ULong fSrcDevAddr;
ULong fDstDevAddr;
UByte fFlags;
UByte fSlotNum;
UByte fVersion;
UByte fDevInfo[2]; };
#define kTSNRMPacketSize 11 // Can't use sizeof because of padding stuff
class TSNRMPacket
{
public:
UByte fPhonyBologna1; UByte fPhonyBalogna2; UByte fAddress;
UByte fCmdRsp;
ULong fSrcDevAddr;
ULong fDstDevAddr;
UByte fConnAddr;
UByte fQOSParmData[3]; };
#define kTUAPacketSize 10 // Can't use sizeof because of padding stuff
class TUAPacket
{
public:
UByte fPhonyBologna1; UByte fPhonyBalogna2; UByte fAddress;
UByte fCmdRsp;
ULong fSrcDevAddr;
ULong fDstDevAddr;
UByte fQOSParmData[4]; };
#define kTControlPacketSize 2 // Can't use sizeof because of padding stuff
class TControlPacket
{
public:
UByte fPhonyBologna1; UByte fPhonyBalogna2; UByte fAddress;
UByte fCmdRsp;
UByte fLMPDUData[4]; };
#define kTFRMRPacketSize 5 // Can't use sizeof because of padding stuff
class TFRMRPacket
{
public:
UByte fAddress;
UByte fCmdRsp;
UByte fRejCtrlField;
UByte fMyNrAndNs;
UByte fReasonFlags;
UByte fPhonyBologna1; UByte fPhonyBalogna2; UByte fPhonyBalogna3; };
#define kTTestHdrPacketSize 2 // Can't use sizeof because of padding stuff
class TTestHdrPacket
{
public:
UByte fAddress;
UByte fCmdRsp;
};
class TIrLAPPutBuffer : public OSObject
{
OSDeclareDefaultStructors(TIrLAPPutBuffer);
public:
static TIrLAPPutBuffer * tIrLAPPutBuffer(void); void free(void);
bool init();
void SetControlBuffer(UByte* buffer, ULong length, Boolean initFirst);
void SetDataBuffer(CBuffer* buffer, ULong offset, ULong length);
UByte Get(void);
void Seek(Long off, int dir);
Boolean AtEOF(void) const;
ULong GetCtrlSize ( void );
UByte * GetCtrlBuffer ( void );
ULong GetDataSize ( void );
UByte * GetDataBuffer ( void );
private:
UByte* fCtrlBuf;
ULong fCtrlBufLength;
ULong fCtrlBufPos;
CBuffer* fDataBuf;
ULong fDataBufOffset;
ULong fDataBufLength;
ULong fDataBufPos;
};
inline ULong TIrLAPPutBuffer::GetCtrlSize() { return fCtrlBufLength; }
inline UByte * TIrLAPPutBuffer::GetCtrlBuffer() { return fCtrlBuf; }
inline ULong TIrLAPPutBuffer::GetDataSize() { return fDataBufLength; }
inline UByte * TIrLAPPutBuffer::GetDataBuffer() { return fDataBuf ? ((CBufferSegment *)fDataBuf)->GetBufferPtr() : nil; };
class TIrLAP : public TIrStream
{
OSDeclareDefaultStructors(TIrLAP);
public:
static TIrLAP * tIrLAP(TIrGlue *irda, TIrQOS *myQOS, TIrQOS* peerQOS);
Boolean Init(TIrGlue *irda, TIrQOS *myQOS, TIrQOS* peerQOS);
void free(void);
void Reset();
void TimerComplete(ULong refCon);
void OutputComplete();
void ChangeSpeedComplete();
void InputComplete(UByte aField, UByte cField);
Boolean InputAborted();
void CopyStatsTo(TCMOSlowIRStats* irStats);
void ResetStats();
void ReleaseInputBuffer(CBufferSegment* inputBuffer);
ULong GetMyDevAddr() { return fMyDevAddr; }
UInt32 GetDisconnectTimeoutMax ( void );
UInt32 GetDisconnectTime ( void );
Boolean InBrokenBeam ( void );
Boolean Discovering ( void );
Boolean ReaquiredConnection ( void );
void BrokenBeamDisconnect ( void );
Boolean IsConnected ( void );
void GetNickName ( UInt8 * name, int maxlen);
TIrEvent * CancelPendingListenRequest (void);
void DisconnectComplete(IrDAErr result = errConnectionAborted);
TIrEvent * GetCurrentRequest(void);
void Suspend(void); void Resume(void);
private:
void NextState(ULong event);
void DeInit();
void FreeGetBuffers();
void HandleDisconnectedStateEvent(ULong event);
void HandleQueryStateEvent(ULong event);
void HandleConnectStateEvent(ULong event);
void HandleListenStateEvent(ULong event);
void HandleReplyStateEvent(ULong event);
void HandleNDMDisconnectRequest();
void HandlePriTransmitStateEvent(ULong event);
void HandlePriReceiveStateEvent(ULong event);
void HandlePriCloseStateEvent(ULong event);
void HandleSecTransmitStateEvent(ULong event);
void HandleSecReceiveStateEvent(ULong event);
void HandleSecCloseStateEvent(ULong event);
void UpdateNrReceived();
void ResendRejectedFrames();
void ProcessRecdInfoOrSuperFrame();
IrDAErr ParseNegotiateAndInitConnState(Boolean primary);
void ConnLstnComplete(IrDAErr result);
void CancelPutRequest();
void CancelPendingPutRequests(TLSAPConn* lsapConn, IrDAErr returnCode);
void PutComplete(TIrPutReply* putReply, IrDAErr result);
void NotConnectedCompletion();
void ApplyDefaultConnParms();
void StartDataReceive();
void PostponePutRequest();
void PrepareFRMRResponse();
void OutputXIDCommand();
void OutputXIDResponse(TXIDPacket& xidCmd);
void OutputSNRMCommand();
void OutputUAResponse();
void OutputFRMRResponse();
void OutputControlFrame(UByte cmdRsp);
void OutputDataFrame(TIrPutRequest* request, Boolean finalOrPollFlag);
Boolean GotData(UByte *data, ULong size);
Boolean RecdCmd(UByte cmdPattern);
Boolean RecdPollCmd(UByte cmdPattern);
Boolean RecdRsp(UByte rspPattern);
Boolean RecdFinalRsp(UByte rspPattern);
Boolean Recd(UByte cmdRsp) { return fRecdCmdRsp == cmdRsp; }
Boolean RecdCmd() { return fRecdCR == kIrLAPCommandBit; }
Boolean RecdRsp() { return fRecdCR != kIrLAPCommandBit; }
Boolean RecdPoll() { return fRecdPF; }
Boolean RecdFinal() { return fRecdPF; }
Boolean RecdPollOrFinal() { return fRecdPF; }
Boolean RecdUFrame() { return (fRecdCmdRsp & kIrLAPUSIMask) == kIrLAPUnnumbered; }
Boolean RecdSFrame() { return (fRecdCmdRsp & kIrLAPUSIMask) == kIrLAPSupervisory; }
Boolean RecdIFrame() { return (fRecdCmdRsp & kIrLAPIMask) == kIrLAPInformation; }
Boolean RecdInvalidNr() { return (fNrNsFlags & kIrLAPInvalidNr) != 0; }
Boolean RecdInvalidNs() { return (fNrNsFlags & kIrLAPInvalidNs) != 0; }
Boolean RecdInvalidNrOrNs() { return (fNrNsFlags & (kIrLAPInvalidNr | kIrLAPInvalidNs)) != 0;}
Boolean RecdUnexpectedNr() { return (fNrNsFlags & kIrLAPUnexpectedNr) != 0; }
Boolean RecdUnexpectedNs() { return (fNrNsFlags & kIrLAPUnexpectedNs) != 0; }
void StartTimer(TTimeout timeDelay, int refCon);
void StopTimer();
void StartOutput(TIrLAPPutBuffer* outputBuffer, ULong leadInCount);
void StopOutput();
void StartInput(CBufferSegment* inputBuffer);
void StopInput();
void HandleTestFrame();
void TestFrameComplete();
void RejectRequest(TIrEvent *request, IrDAErr err);
UByte fState;
UByte fConnAddr; ULong fMyDevAddr;
UByte fDiscoverMaxSlots;
UByte fDiscoverSlot;
UByte fDiscoverFlags;
Boolean fDiscoverEnteredReplyState;
Boolean fDiscoverReplied;
ULong fConflictDevAddr;
ULong fReplacementDevAddr;
ULong fPeerDevAddr;
TIrEvent *fCurrentRequest; TIrEvent *fPendingDisconnect; CList *fPendingRequests;
TIrQOS *fMyQOS;
TIrQOS *fPeerQOS;
UByte fVr;
UByte fVs;
UByte fNextToAck;
UByte fWindow;
Boolean fConnected; Boolean fLocalBusy;
Boolean fRemoteBusy;
Boolean fSetLocalBusyPending;
Boolean fClrLocalBusyPending;
Boolean fEnteringCloseState;
Boolean fRespondingToDisconnect;
Boolean fWaitingForPollTimer;
Boolean fHandlingTestFrame;
TTestHdrPacket fTestHeader;
Boolean fFRMRPending;
UByte fFRMRRejCtrlField;
UByte fFRMRMyNrAndNs;
UByte fFRMRReasonFlags;
ULong fRetryCount;
ULong fDisconnectWarningLimit;
ULong fDisconnectLinkLimit;
UInt32 fInitialRetryTime;
UInt32 fDisconnectLinkLimitTime;
UInt32 fBusyCounter;
ULong fDataRetries;
ULong fProtocolErrs;
TIrEvent *fLocalBusyClearedEvent;
UByte fLeadInCount;
UByte fMyWindowSize; UByte fPeerWindowSize; TTimeout fPollTimerTimeout;
TTimeout fFinalTimerTimeout;
TTimeout fWatchdogTimeout;
TTimeout fMinTurnAroundTimeout;
Boolean fPrimary;
Boolean fPutReqsPending; UByte fNextCmdRspToSend; UByte fLastCmdRsp;
UByte fRecdCtrl; UByte fRecdCR; UByte fRecdAddr; UByte fRecdPF; UByte fRecdNr; UByte fRecdNs; UByte fRecdCmdRsp;
UByte fValidRecdNr; UByte fValidRecdNs; UByte fNrNsFlags;
CBufferSegment *fIOBufferItem;
Boolean fInputInProgress; Boolean fOutputInProgress;
Boolean fInBrokenBeam; Boolean fDiscoverActive;
ULong fGetBufferAvail;
ULong fNumGetBuffers;
CBufferSegment* fGetBuffers[15];
CBufferSegment* fInputBuffer; UInt8 fNickName[22]; CList* fPendingPutRequests;
TIrLAPPutBuffer *fPutBuffer;
TIrPutRequest *fPutRequests[8];
};
inline UInt32 TIrLAP::GetDisconnectTimeoutMax() { return fDisconnectLinkLimitTime; }
inline UInt32 TIrLAP::GetDisconnectTime() { return fInitialRetryTime; }
inline Boolean TIrLAP::InBrokenBeam() { return fInBrokenBeam; }
inline Boolean TIrLAP::Discovering() { return fDiscoverActive; }
inline Boolean TIrLAP::ReaquiredConnection() { return fRetryCount < fDisconnectWarningLimit; }
inline void TIrLAP::BrokenBeamDisconnect() { if( fInBrokenBeam )
fRetryCount = fDisconnectLinkLimit; }
inline Boolean TIrLAP::IsConnected( void ) { return fConnected; }
inline TIrEvent * TIrLAP::GetCurrentRequest(void) { return fCurrentRequest; }; #endif // __IRLAP_H