1/*
2    File:       IrLAP.h
3
4    Contains:   Methods for implementing IrLAP
5
6*/
7
8
9#ifndef __IRLAP_H
10#define __IRLAP_H
11
12#include "IrDATypes.h"
13#include "IrStream.h"
14#include "CBufferSegment.h"
15#include "IrEvent.h"
16
17// Forward reference
18class TIrGlue;
19class TIrLMP;
20class TIrQOS;
21class TLSAPConn;
22class TCMOSlowIRStats;
23class CIrDiscovery;
24class CIrDevice;
25class CBuffer;
26
27// Constants
28
29#define kIrLAPVersionNumber     0x00
30#define kIrLAPBroadcastAddr     0x7F
31#define kIrLAPCommandBit        0x01
32
33#define kIrLAPBroadcastDevAddr  0xFFFFFFFF
34#define kIrLAPSnifferDevAddr    0x736E6966
35#define kIrLAPSniffeeDevAddr    0x726F7365
36#define kIrLAPProbeDevAddr      0x70726265
37
38#define kIrDefaultLeadinCount   10
39#define kIrLAPFinalSlot         0xFF
40
41
42enum IrLAPCommandsAndResponses
43{
44    kIrLAPUSIMask               = 0x03,
45    kIrLAPIMask                 = 0x01,
46    kIrLAPUnnumbered            = 0x03,
47    kIrLAPSupervisory           = 0x01,
48    kIrLAPInformation           = 0x00,
49
50    kIrLAPPFMask                = 0x10,
51    kIrLAPPollBit               = 0x10,
52    kIrLAPFinalBit              = 0x10,
53
54    kIrLAPNrMask                = 0xE0,
55    kIrLAPNrShift               = 5,
56    kIrLAPNsMask                = 0x0E,
57    kIrLAPNsShift               = 1,
58
59    kIrLAPUnexpectedNr          = 0x01,
60    kIrLAPUnexpectedNs          = 0x02,
61    kIrLAPInvalidNr             = 0x04,
62    kIrLAPInvalidNs             = 0x08,
63
64    // Unnumbered commands
65    kIrLAPCmdSNRM               = 0x83,
66    kIrLAPCmdDISC               = 0x43,
67    kIrLAPCmdUI                 = 0x03,
68    kIrLAPCmdXID                = 0x2F,
69    kIrLAPCmdTEST               = 0xE3,
70
71    // Unnumbered responses
72    kIrLAPRspRNRM               = 0x83,
73    kIrLAPRspUA                 = 0x63,
74    kIrLAPRspFRMR               = 0x87,
75    kIrLAPRspDM                 = 0x0F,
76    kIrLAPRspRD                 = 0x43,
77    kIrLAPRspUI                 = 0x03,
78    kIrLAPRspXID                = 0xAF,
79    kIrLAPRspTEST               = 0xE3,
80
81    // Supervisor cmd/rsp
82    kIrLAPFrameRR               = 0x01,
83    kIrLAPFrameRNR              = 0x05,
84    kIrLAPFrameREJ              = 0x09,
85    kIrLAPFrameSREJ             = 0x0D,
86
87    // Information
88    kIrLAPFrameINFO             = 0x00
89};
90
91enum IrLAPFormatIdentifiers
92{
93    kIrLAPDiscoveryXIDFormat    = 0x01
94};
95
96enum IrLAPDiscoverFlags
97{
98    kIrLAPDiscoverFlagsSlotMask = 0x03,
99    kIrLAPDiscoverFlags1Slot    = 0x00,
100    kIrLAPDiscoverFlags6Slots   = 0x01,
101    kIrLAPDiscoverFlags8Slots   = 0x02,
102    kIrLAPDiscoverFlags16Slots  = 0x03,
103
104    kIrLAPDiscoverFlagsNewAddr  = 0x04
105};
106
107enum IrFRMRFlags    // w,x,y,z fields of third FRMR I-field
108{
109    kIrFRMRFlagUndefinedCtrl    = 0x01,
110    kIrFRMRFlagInvalidIField    = 0x02,
111    kIrFRMRFlagSizeExceeded     = 0x04,
112    kIrFRMRFlagInvalidNrCount   = 0x08,
113
114    kIrFRMRCrBit                = 0x10
115};
116
117enum IrLAPStates
118{
119    kIrLAPDisconnectedState,                /* NDM */
120    kIrLAPQueryState,                       /* Discover query from primary */
121    kIrLAPConnectState,                     /* Connect from primary */
122    kIrLAPListenState,                      /* Listen from secondary */
123    kIrLAPReplyState,                       /* Discover reply from secondary */
124
125    kIrLAPLastNDMState          = kIrLAPReplyState,
126
127    kIrLAPPriReceiveState,                  /* Primary in NRM receive */
128    kIrLAPPriTransmitState,                 /* Primary in NRM transmit */
129    kIrLAPPriCloseState,                    /* Primary in NRM close */
130    kIrLAPSecReceiveState,                  /* Secondary in NRM receive */
131    kIrLAPSecTransmitState,                 /* Secondary in NRM transmit */
132    kIrLAPSecCloseState                     /* Secondary in NRM close */
133};
134
135enum IrLAPTimings       // in milliseconds
136{
137    kIrMediaBusyTimeout         = 600,
138    kIrDiscoverSlotTimeout      = 100,      // *** Review - should be 60 (or35 if done right)
139    kIrConnectFinalTimerTimeout = 500,      // *** Review - is this right?
140    kIrDisconnectWarningTimeout = 3 * 1000  // 3 seconds
141};
142
143enum IrLAPRetries
144{
145    kMaxConnectRetries          = 3,
146    kMaxDisconnectRetries       = 3,
147    kMaxDiscoverRetries         = 10        // JDG: max times mediabusy timer fires before 1st discover
148};
149
150enum  {
151    kMaxUnconnectedPacketSize   = 64
152};
153
154// Classes
155
156
157// --------------------------------------------------------------------------------------------------------------------
158//                      TXIDPacket
159// --------------------------------------------------------------------------------------------------------------------
160
161#define kTXIDPacketSize     14                      // Can't use sizeof because of padding stuff
162
163class TXIDPacket
164{
165    public:
166
167	    UByte           fPhonyBologna1;         // Ensure alignment of the following�
168	    UByte           fAddress;
169	    UByte           fCmdRsp;
170	    UByte           fFormatId;
171	    ULong           fSrcDevAddr;
172	    ULong           fDstDevAddr;
173	    UByte           fFlags;
174	    UByte           fSlotNum;
175	    UByte           fVersion;
176	    UByte           fDevInfo[2];            // Device info, actually longer, just padding
177};
178
179
180// --------------------------------------------------------------------------------------------------------------------
181//                      TSNRMPacket
182// --------------------------------------------------------------------------------------------------------------------
183
184#define kTSNRMPacketSize    11                      // Can't use sizeof because of padding stuff
185
186class TSNRMPacket
187{
188    public:
189
190	    UByte           fPhonyBologna1;         // Ensure alignment of the following�
191	    UByte           fPhonyBalogna2;         // Ensure alignment of the following�
192	    UByte           fAddress;
193	    UByte           fCmdRsp;
194	    ULong           fSrcDevAddr;
195	    ULong           fDstDevAddr;
196	    UByte           fConnAddr;
197	    UByte           fQOSParmData[3];        // QOS parm info, actually longer, just padding
198};
199
200
201// --------------------------------------------------------------------------------------------------------------------
202//                      TUAPacket
203// --------------------------------------------------------------------------------------------------------------------
204
205#define kTUAPacketSize      10                      // Can't use sizeof because of padding stuff
206
207class TUAPacket
208{
209    public:
210
211	    UByte           fPhonyBologna1;         // Ensure alignment of the following�
212	    UByte           fPhonyBalogna2;         // Ensure alignment of the following�
213	    UByte           fAddress;
214	    UByte           fCmdRsp;
215	    ULong           fSrcDevAddr;
216	    ULong           fDstDevAddr;
217	    UByte           fQOSParmData[4];        // QOS parm info, actually longer, just padding
218};
219
220
221// --------------------------------------------------------------------------------------------------------------------
222//                      TControlPacket
223// --------------------------------------------------------------------------------------------------------------------
224
225#define kTControlPacketSize     2                   // Can't use sizeof because of padding stuff
226
227class TControlPacket
228{
229    public:
230
231	    UByte           fPhonyBologna1;         // Ensure alignment of the following�
232	    UByte           fPhonyBalogna2;         // Ensure alignment of the following�
233	    UByte           fAddress;
234	    UByte           fCmdRsp;
235	    UByte           fLMPDUData[4];          // Up to 4 bytes
236};
237
238
239// --------------------------------------------------------------------------------------------------------------------
240//                      TFRMRPacket
241// --------------------------------------------------------------------------------------------------------------------
242
243#define kTFRMRPacketSize        5                   // Can't use sizeof because of padding stuff
244
245class TFRMRPacket
246{
247    public:
248
249	    UByte           fAddress;
250	    UByte           fCmdRsp;
251	    UByte           fRejCtrlField;
252	    UByte           fMyNrAndNs;
253	    UByte           fReasonFlags;
254	    UByte           fPhonyBologna1;         // Pad it out (sheer paranoia)
255	    UByte           fPhonyBalogna2;         // Pad it out (sheer paranoia)
256	    UByte           fPhonyBalogna3;         // Pad it out (sheer paranoia)
257};
258
259
260// --------------------------------------------------------------------------------------------------------------------
261//                      TTestHdrPacket
262// --------------------------------------------------------------------------------------------------------------------
263
264#define kTTestHdrPacketSize     2                   // Can't use sizeof because of padding stuff
265
266class TTestHdrPacket
267{
268    public:
269
270	    UByte           fAddress;
271	    UByte           fCmdRsp;
272};
273
274
275//--------------------------------------------------------------------------------
276//      TIrLAPPutBuffer
277//--------------------------------------------------------------------------------
278class TIrLAPPutBuffer : public OSObject
279{
280    OSDeclareDefaultStructors(TIrLAPPutBuffer);
281
282public:
283	    static TIrLAPPutBuffer * tIrLAPPutBuffer(void);    // factory constructor
284	    void            free(void);
285	    bool            init();
286
287	    void            SetControlBuffer(UByte* buffer, ULong length, Boolean initFirst);
288	    void            SetDataBuffer(CBuffer* buffer, ULong offset, ULong length);
289
290	    UByte           Get(void);
291	    void            Seek(Long off, int dir);
292	    Boolean         AtEOF(void) const;
293	    ULong           GetCtrlSize     ( void );
294	    UByte       *   GetCtrlBuffer   ( void );
295	    ULong           GetDataSize     ( void );
296	    UByte       *   GetDataBuffer   ( void );
297
298private:
299	    // Fields�
300	    UByte*          fCtrlBuf;
301	    ULong           fCtrlBufLength;
302	    ULong           fCtrlBufPos;
303
304	    CBuffer*        fDataBuf;
305	    ULong           fDataBufOffset;
306	    ULong           fDataBufLength;
307	    ULong           fDataBufPos;
308};
309
310inline ULong    TIrLAPPutBuffer::GetCtrlSize()      { return fCtrlBufLength; }
311inline UByte *  TIrLAPPutBuffer::GetCtrlBuffer()    { return fCtrlBuf; }
312inline ULong    TIrLAPPutBuffer::GetDataSize()      { return fDataBufLength; }
313inline UByte *  TIrLAPPutBuffer::GetDataBuffer()    { return fDataBuf ? ((CBufferSegment *)fDataBuf)->GetBufferPtr() : nil; };
314
315
316// --------------------------------------------------------------------------------------------------------------------
317//                      TIrLAP
318// --------------------------------------------------------------------------------------------------------------------
319
320class TIrLAP : public TIrStream
321{
322    OSDeclareDefaultStructors(TIrLAP);
323
324    public:
325
326	    static TIrLAP * tIrLAP(TIrGlue *irda, TIrQOS *myQOS, TIrQOS* peerQOS);
327	    Boolean         Init(TIrGlue *irda, TIrQOS *myQOS, TIrQOS* peerQOS);
328	    void            free(void);
329
330	    void            Reset();
331
332	    // Callback for timer completion
333
334	    void            TimerComplete(ULong refCon);
335
336	    // Callbacks for I/O completion
337
338	    void            OutputComplete();
339	    void            ChangeSpeedComplete();      // jdg
340
341	    void            InputComplete(UByte aField, UByte cField);
342	    Boolean         InputAborted();         // read failed
343
344	    // Access to IrLAP level stats
345
346	    void            CopyStatsTo(TCMOSlowIRStats* irStats);
347	    void            ResetStats();
348
349	    // To return input buffer to the buffer pool
350
351	    void            ReleaseInputBuffer(CBufferSegment* inputBuffer);
352
353	    // Inline getter for my device address (for address resolution checking)
354
355	    ULong           GetMyDevAddr()              { return fMyDevAddr;    }
356
357	    UInt32          GetDisconnectTimeoutMax     ( void );
358	    UInt32          GetDisconnectTime           ( void );
359	    Boolean         InBrokenBeam                ( void );
360	    Boolean         Discovering                 ( void );
361	    Boolean         ReaquiredConnection         ( void );
362	    void            BrokenBeamDisconnect        ( void );
363	    Boolean         IsConnected                 ( void );
364	    void            GetNickName                 ( UInt8 * name, int maxlen);
365										// jdg: stop listen if in disconnected state
366	    TIrEvent *      CancelPendingListenRequest  (void);                 // return event if canceled, else nil
367/*** Temp I hope ***/
368/***JDG***/ void            DisconnectComplete(IrDAErr result = errConnectionAborted);
369	    TIrEvent *      GetCurrentRequest(void);        // jdg: ugly hack #2341
370
371	    void            Suspend(void);          // jdg: going to sleep mode
372	    void            Resume(void);           // jdg: waking up from sleep
373
374    private:
375
376	    // TIrStream override
377	    void            NextState(ULong event);
378
379	    void            DeInit();
380	    void            FreeGetBuffers();
381
382	    // NDM states
383	    void            HandleDisconnectedStateEvent(ULong event);
384	    void            HandleQueryStateEvent(ULong event);
385	    void            HandleConnectStateEvent(ULong event);
386	    void            HandleListenStateEvent(ULong event);
387	    void            HandleReplyStateEvent(ULong event);
388	    void            HandleNDMDisconnectRequest();
389
390	    // NRM states
391	    void            HandlePriTransmitStateEvent(ULong event);
392	    void            HandlePriReceiveStateEvent(ULong event);
393	    void            HandlePriCloseStateEvent(ULong event);
394	    void            HandleSecTransmitStateEvent(ULong event);
395	    void            HandleSecReceiveStateEvent(ULong event);
396	    void            HandleSecCloseStateEvent(ULong event);
397
398	    void            UpdateNrReceived();
399	    void            ResendRejectedFrames();
400	    void            ProcessRecdInfoOrSuperFrame();
401
402	    IrDAErr         ParseNegotiateAndInitConnState(Boolean primary);
403	    void            ConnLstnComplete(IrDAErr result);
404	//  void            DisconnectComplete(IrDAErr result = kCommErrConnectionAborted);
405	    void            CancelPutRequest();
406	    void            CancelPendingPutRequests(TLSAPConn* lsapConn, IrDAErr returnCode);
407	    void            PutComplete(TIrPutReply* putReply, IrDAErr result);
408	    void            NotConnectedCompletion();
409	    void            ApplyDefaultConnParms();
410	    void            StartDataReceive();
411
412	    void            PostponePutRequest();
413	    void            PrepareFRMRResponse();
414
415	    void            OutputXIDCommand();
416	    void            OutputXIDResponse(TXIDPacket& xidCmd);
417	    void            OutputSNRMCommand();
418	    void            OutputUAResponse();
419	    void            OutputFRMRResponse();
420	    void            OutputControlFrame(UByte cmdRsp);
421	    void            OutputDataFrame(TIrPutRequest* request, Boolean finalOrPollFlag);
422
423	    Boolean         GotData(UByte *data, ULong size);
424	    Boolean         RecdCmd(UByte cmdPattern);
425	    Boolean         RecdPollCmd(UByte cmdPattern);
426	    Boolean         RecdRsp(UByte rspPattern);
427	    Boolean         RecdFinalRsp(UByte rspPattern);
428
429	    Boolean         Recd(UByte cmdRsp)      { return fRecdCmdRsp == cmdRsp;         }
430	    Boolean         RecdCmd()               { return fRecdCR == kIrLAPCommandBit;   }
431	    Boolean         RecdRsp()               { return fRecdCR != kIrLAPCommandBit;   }
432	    Boolean         RecdPoll()              { return fRecdPF;   }
433	    Boolean         RecdFinal()             { return fRecdPF;   }
434	    Boolean         RecdPollOrFinal()       { return fRecdPF;   }
435
436	    Boolean         RecdUFrame()            { return (fRecdCmdRsp & kIrLAPUSIMask) == kIrLAPUnnumbered;     }
437	    Boolean         RecdSFrame()            { return (fRecdCmdRsp & kIrLAPUSIMask) == kIrLAPSupervisory;    }
438	    Boolean         RecdIFrame()            { return (fRecdCmdRsp & kIrLAPIMask) == kIrLAPInformation;      }
439
440	    Boolean         RecdInvalidNr()         { return (fNrNsFlags & kIrLAPInvalidNr) != 0;                   }
441	    Boolean         RecdInvalidNs()         { return (fNrNsFlags & kIrLAPInvalidNs) != 0;                   }
442	    Boolean         RecdInvalidNrOrNs()     { return (fNrNsFlags & (kIrLAPInvalidNr | kIrLAPInvalidNs)) != 0;}
443	    Boolean         RecdUnexpectedNr()      { return (fNrNsFlags & kIrLAPUnexpectedNr) != 0;                }
444	    Boolean         RecdUnexpectedNs()      { return (fNrNsFlags & kIrLAPUnexpectedNs) != 0;                }
445
446	    void            StartTimer(TTimeout timeDelay, int refCon);
447	    void            StopTimer();
448
449	    void            StartOutput(TIrLAPPutBuffer* outputBuffer, ULong leadInCount);
450	    void            StopOutput();
451	    void            StartInput(CBufferSegment* inputBuffer);
452	    void            StopInput();
453
454	    void            HandleTestFrame();
455	    void            TestFrameComplete();
456
457	    void            RejectRequest(TIrEvent *request, IrDAErr err);  // jdg, send back a request w/error
458
459	    // Fields�
460
461	    UByte           fState;
462	    UByte           fConnAddr;              // The 'A' field address
463	    ULong           fMyDevAddr;
464
465	    UByte           fDiscoverMaxSlots;
466	    UByte           fDiscoverSlot;
467	    UByte           fDiscoverFlags;
468	    Boolean         fDiscoverEnteredReplyState;
469	    Boolean         fDiscoverReplied;
470	    ULong           fConflictDevAddr;
471	    ULong           fReplacementDevAddr;
472
473	    ULong           fPeerDevAddr;
474
475	    TIrEvent        *fCurrentRequest;       // For discover, connect, listen
476	    TIrEvent        *fPendingDisconnect;    // For pending disconnect
477	    CList           *fPendingRequests;      // jdg: deferred requests
478
479	    TIrQOS          *fMyQOS;
480	    TIrQOS          *fPeerQOS;
481
482	    UByte           fVr;
483	    UByte           fVs;
484	    UByte           fNextToAck;
485	    UByte           fWindow;
486	    Boolean         fConnected;                 // Is LAP connected?
487	    Boolean         fLocalBusy;
488	    Boolean         fRemoteBusy;
489	    Boolean         fSetLocalBusyPending;
490	    Boolean         fClrLocalBusyPending;
491	    Boolean         fEnteringCloseState;
492	    Boolean         fRespondingToDisconnect;
493
494	    Boolean         fWaitingForPollTimer;       // avoiding cycle comsumption while idle or busy
495
496	    Boolean         fHandlingTestFrame;
497	    TTestHdrPacket  fTestHeader;
498
499	    Boolean         fFRMRPending;
500	    UByte           fFRMRRejCtrlField;
501	    UByte           fFRMRMyNrAndNs;
502	    UByte           fFRMRReasonFlags;
503
504	    ULong           fRetryCount;
505	    ULong           fDisconnectWarningLimit;
506	    ULong           fDisconnectLinkLimit;
507
508	    UInt32          fInitialRetryTime;
509	    UInt32          fDisconnectLinkLimitTime;
510	    UInt32          fBusyCounter;       // JDG: number of media busy in a row
511
512	    ULong           fDataRetries;
513	    ULong           fProtocolErrs;
514
515	    //TIrEvent      *fLocalBusyEvent;           // Review.  Why is this not referenced?
516	    TIrEvent        *fLocalBusyClearedEvent;    // REVIEW.  How is this used?
517
518	    UByte           fLeadInCount;
519	    UByte           fMyWindowSize;          // Number of recv buffers - from fMyQOS->GetWindowSize()
520	    UByte           fPeerWindowSize;        // Number of recv buffers - from fPeerQOS->GetWindowSize()
521	    TTimeout        fPollTimerTimeout;
522	    TTimeout        fFinalTimerTimeout;
523	    TTimeout        fWatchdogTimeout;
524	    TTimeout        fMinTurnAroundTimeout;
525
526	    Boolean         fPrimary;
527	    //Boolean       fNeedNewInputBuffer;    // if fInputBuffer is nil, then we need a new one
528	    Boolean         fPutReqsPending;        // One or more addl put reqs pending for secondary?
529	    UByte           fNextCmdRspToSend;      // Cmd to send after recv cmd is processed
530	    UByte           fLastCmdRsp;            // The last packet type sent.
531
532	    UByte           fRecdCtrl;              // Control field as received (only used w/FRMR)
533	    UByte           fRecdCR;                // C/R bit of the A field
534	    UByte           fRecdAddr;              // Addr bits of the A field
535	    UByte           fRecdPF;                // PF bit of the C field
536	    UByte           fRecdNr;                // Nr bits of the C field
537	    UByte           fRecdNs;                // Ns bits of the C field
538	    UByte           fRecdCmdRsp;            // C field (less P/F, Nr, Ns)
539
540	    UByte           fValidRecdNr;           // Bits representing valid fRecdNr values
541	    UByte           fValidRecdNs;           // Bits representing valid fRecdNs values
542	    UByte           fNrNsFlags;             // Unexpected/invalid Nr/Ns flags
543
544	    //ULong         fIOBuffer[64/4];        // Note: must be ULong for alignment!
545	    CBufferSegment  *fIOBufferItem;         // used for misc i/o and when out of input buffers.
546
547	    Boolean         fInputInProgress;       // Waiting for input (or perhaps receiving data)
548	    Boolean         fOutputInProgress;      // Outputting data
549
550	    Boolean         fInBrokenBeam;          // true if the beam is broken (but connection still exists)
551	    Boolean         fDiscoverActive;        // true if we're discovering
552
553	    ULong           fGetBufferAvail;
554	    ULong           fNumGetBuffers;
555	    CBufferSegment* fGetBuffers[15];        // Was 8, have 2*window for
556						    // a workaround
557
558	    CBufferSegment* fInputBuffer;           // either fIOBufferItem or one of fGetBuffers
559	    //CList         fPendingPuts;
560	    UInt8           fNickName[22];          // Name of device connected to.
561	    CList*          fPendingPutRequests;
562	    TIrLAPPutBuffer *fPutBuffer;
563	    TIrPutRequest   *fPutRequests[8];
564
565};
566
567inline  UInt32  TIrLAP::GetDisconnectTimeoutMax()   { return fDisconnectLinkLimitTime; }
568inline  UInt32  TIrLAP::GetDisconnectTime()         { return fInitialRetryTime; }
569inline  Boolean TIrLAP::InBrokenBeam()              { return fInBrokenBeam; }
570inline  Boolean TIrLAP::Discovering()               { return fDiscoverActive;   }
571inline  Boolean TIrLAP::ReaquiredConnection()       { return fRetryCount < fDisconnectWarningLimit; }
572inline  void    TIrLAP::BrokenBeamDisconnect()      { if( fInBrokenBeam )
573							fRetryCount = fDisconnectLinkLimit; }
574inline  Boolean TIrLAP::IsConnected( void )         { return fConnected; }
575
576inline TIrEvent * TIrLAP::GetCurrentRequest(void)   { return fCurrentRequest; };    // jdg, temp?
577#endif // __IRLAP_H
578