1/*
2    File:       ttp2.cpp
3
4    Contains:   Tiny TP Implementations of callbacks by CIrLSAP
5
6
7*/
8
9#include "ttp.h"
10#include "ttppdu.h"
11#include "CBufferSegment.h"
12
13// Contents:   this module contains all of the TinyTP callbacks that
14//              are invoked (one way or another) by CIrLSAP when something
15//              happens worth telling us about
16
17#if (hasTracing > 0 && hasTTP2Tracing > 0)
18
19enum IrTinyTP2TraceCodes
20{
21    kHandleConnectIndication = 1,
22    kHandleConnectConfirm,
23    kHandleDisconnectIndication,
24    kHandleDataIndication,
25    kDataLessPacket
26};
27
28static
29EventTraceCauseDesc gTraceEvents[] = {
30    {kHandleConnectIndication,      "TinyTP2: connect indication"},
31    {kHandleConnectConfirm,         "TinyTP2: connect confirm"},
32    {kHandleDisconnectIndication,   "TinyTP2: disconnect indication"},
33    {kHandleDataIndication,         "TinyTP2: data indication"},
34    {kDataLessPacket,               "TinyTP2: dataless indication"}
35};
36
37#define XTRACE(x, y, z)  IrDALogAdd( x, y, z, gTraceEvents, true )
38
39#else
40    #define XTRACE(x, y, z) ((void)0)
41#endif
42
43
44void
45TTinyTP::TTPHandleConnectIndication (
46	IrDAErr result,
47	TTPSAP  sap,                        // calling TTP SAP
48	TIrQOS  *ourQOS,                    // our QoS
49	TIrQOS  *peerQOS,                   // peer QoS
50	TTPBuf  *userData)                  // calling UserData
51{
52    unsigned char plist[100];       // enough for me ...
53    int     p;                      // parameters?
54    int     n;                      // initial credit
55
56    XTRACE(kHandleConnectIndication, 0, result);
57    if (result != noErr) {
58	TTPConnectIndication(result, sap, ourQOS, peerQOS, this->TxMaxSduSize, userData);   // virtual callback
59	return;
60    }
61
62    ttp_pdu_connect_parse(userData, &p, &n, &plist[0]); // strips out ttp pdu params
63    this->SendCredit = n;
64    this->TxMaxSduSize = 0;
65    //this->MaxSegSize = MaxTxIrLapDataSize - 3;
66    this->MaxSegSize = peerQOS->GetDataSize() - 3;      // get max send pkt size
67
68    if (p == 1) {
69	UInt32 value;
70	if (ttp_pdu_connect_get_max_sdu_size(plist, &value))
71	    this->TxMaxSduSize = value;
72    }
73
74    TTPConnectIndication(result, sap, ourQOS, peerQOS, this->TxMaxSduSize, userData);   // virtual callback
75    //BufFree(userData);                                // we'll free up the userData now ...
76    // nope -- this buffer was passed to us in a listen request, let our client free it too.
77}
78
79void
80TTinyTP::TTPHandleConnectConfirm (
81	TTPSAP  sap,                        // calling TTP SAP
82	TIrQOS  *ourQOS,                    // our QoS
83	TIrQOS  *peerQOS,                   // peer QoS
84	TTPBuf  *userData)                  // calling UserData
85{
86    unsigned char plist[100];       // enough for me ...
87    int     p;                      // parameters?
88    int     n;                      // initial credit
89
90    XTRACE(kHandleConnectConfirm, 0, 0);
91
92    ttp_pdu_connect_parse(userData, &p, &n, &plist[0]); // strips out ttp pdu params
93    this->SendCredit = n;
94    this->TxMaxSduSize = 0;
95    //this->MaxSegSize = MaxTxIrLapDataSize - 3;
96    this->MaxSegSize = peerQOS->GetDataSize() - 3;      // get max send pkt size
97
98    if (p == 1) {
99	UInt32 value;
100	if (ttp_pdu_connect_get_max_sdu_size(plist, &value))
101	    this->TxMaxSduSize = value;
102	XTRACE(kHandleConnectConfirm, 1, value);
103    }
104
105    this->Connected = true;         // change state before my callback does more work!
106
107
108    // this is a rather different ... as soon as the TTP session is open, hang a read
109    // on the connection.  every time a read completes, pass the buffer up, allocate
110    // a new one, and hang another read out.   TTP Client is responsible for eventually
111    // freeing the buffers passed to it via DataIndication().
112    {   CBufferSegment *getBuf;
113	getBuf = BufAlloc(2048+5);      // need up to max lap size
114	require(getBuf, NoMem);         // not a lot I can do w/out a read buffer
115	this->DataGet(getBuf);          // start the read
116    }
117
118    // Now that the read is pending, tell the client .... (was in other order)
119    TTPConnectConfirm(sap, ourQOS, peerQOS, this->TxMaxSduSize, userData);  // virtual callback to ttp client
120    BufFree(userData);          // free the connect buffer allocated by PDU Connect
121NoMem:
122    return;
123}
124
125void
126TTinyTP::TTPHandleDisconnectIndication (
127	int     reason,                     // passed up from IrLMP
128	TTPBuf  *userData)
129{
130    XTRACE(kHandleDisconnectIndication, 0, 0);
131
132    this->Connected = false;
133    this->FlushQueue(&(this->TxQueue));
134    txQDepth = 0;
135    this->AppendTail(&(this->RxQueue), TTP_Disconnect, reason, userData);
136}
137
138void
139TTinyTP::TTPHandleDataIndication (
140    TTPBuf  *userData)                  // data read
141{
142    int credit;
143    Boolean m;
144
145    check(userData);
146    {   int position, bufsize;
147	position = BufUsed(userData);       // should be zero
148	bufsize  = BufSize(userData);       // amount read
149	XTRACE(kHandleDataIndication, position, bufsize);
150    }
151
152    ttp_pdu_data_parse(userData, &m, &credit);  // strips out ttp overhead byte
153    this->SendCredit += credit;
154    if (SendCredit > 30) SendCredit = 30;       // FIXME: temp workaround for HP runaway credits
155					// WARNING: HP tells us that Microsoft believes in
156					// extending lots and lots of credits, and relies on
157					// lap-layer flow control to survive.
158
159    if (credit > 0)                     // if we've been given more credits from IrLan box
160	TTPBackEnable();                // then tell clients flow-control state has changed
161
162    if (BufSize(userData) > 0) {
163	XTRACE(kHandleDataIndication, m, credit);           // log what we parsed
164	this->RemoteCredit--;
165	if (m == false)         // if no More data
166	    this->AppendTail(&(this->RxQueue), TTP_Segment_Last, 0, userData);
167	else                    // else have More data
168	    this->AppendTail(&(this->RxQueue), TTP_Segment, 0, userData);
169    }
170    else {
171	XTRACE(kDataLessPacket, m, credit);     // log we received a dataless packet
172	BufFree(userData);                      // we're done with it now...
173    }
174
175    // Make sure a read is pending at all times .... this could
176    // use a better model.  Only post if connected.
177    if( this->Connected )
178    {   CBufferSegment *getBuf;
179	getBuf = BufAlloc(2048+5);      // need up to max lap size
180	require(getBuf, NoMem);
181	this->DataGet(getBuf);
182    }
183NoMem:
184    return;
185}
186
187void
188TTinyTP::TTPHandleUDataIndication (
189    TTPBuf  *userData)                  // data read
190{
191    //DebugLog("How'd I get here?  TTinyTP::HandleUDataIndication");
192    TTPUDataIndication(userData);
193}
194
195void
196TTinyTP::TTPHandleAcceptComplete(IrDAErr result, TTPBuf *userdata)
197{
198    check(userdata);
199    BufFree(userdata);          // free buffer alloc'd by ttp.c in accept routine
200    TTPAcceptDoneIndication(result);    // just result, no buffer, since we copied clients during accept
201}
202
203