1/*
2    File:       ttppdu.cpp
3
4    Contains:   TinyTP PDU & buffer subroutines
5
6*/
7
8#include "ttp.h"
9#include "ttppdu.h"
10#include "CBufferSegment.h"
11#include "IrDALog.h"
12
13#if(hasTracing > 0 && hasTTPPduTracing > 0)
14
15enum IrTinyTPpduTraceCodes
16{
17    kPduConnect = 1,
18    kPduConnectParse,
19    kPduGetMax,
20    kPduData,
21    kPduDataParse,
22    kBufferHideRest
23};
24
25static
26EventTraceCauseDesc gTraceEvents[] = {
27    {kPduConnect,       "TinyTPpdu: connect"},
28    {kPduConnectParse,  "TinyTPpdu: connect parse"},
29    {kPduGetMax,        "TinyTPpdu: Get Sdu Max"},
30    {kPduData,          "TinyTPpdu: data"},
31    {kPduDataParse,     "TinyTPpdu: data parse, ttp byte=, bufsize="},
32    {kBufferHideRest,   "TinyTPpdu: buffer hide rest"}
33};
34
35#define XTRACE(x, y, z)  IrDALogAdd( x, y, z, gTraceEvents, true )
36
37#else
38    #define XTRACE(x, y, z) ((void)0)
39#endif
40
41
42// allocates a new TTPBuf and fills it in with the parameter list (if any)
43// followed by the userdata (if any)
44// at a minimum, the result has the first byte with P and initial credit set
45// ToDo: look into doing this in-place w/out an allocate/free issue
46TTPBuf *
47ttp_pdu_connect(int p, int initialCredit, int maxSduSize, TTPBuf *data)
48{
49    TTPBuf *m;          // return message
50    int    datalen;     // length of user data
51    UInt32  byte;
52
53    XTRACE(kPduConnect, initialCredit, maxSduSize);
54
55    if (maxSduSize == 0) {      // don't send zero value maxsdu
56	if (p) { DebugLog("IrDA-TTPPDU: Request to send zero value maxsdu"); }
57	p = 0;
58    }
59    if (data)   datalen = BufSize(data);    // number of bytes of userdata (if any)
60    else        datalen = 0;
61
62    m = BufAlloc(1000);             // get object please
63    require(m, NoMem);                      // no memory
64
65    byte = ((p & 0x01) << 7) | (initialCredit & 0x7f);
66    BufPut(m, byte);
67
68    if (p > 0) {                // any parameters (zero or one really) ...
69	BufPut(m, 4);                   // plen, total length of all parameters
70
71					// first (and only) parameter
72	BufPut(m, PiMaxSduSize);                // PI (parameter id=1)
73	BufPut(m, 2);                           // PL (length of following value)
74	BufPut(m, (maxSduSize >> 8) & 0xff);    // high bits first
75	BufPut(m, maxSduSize & 0xff);           // low bits (big-endian for a change)
76    }
77
78    if (datalen) {                      // copy the userdata portion
79	BufSeekStart(data);                 // make sure we're copying from the start
80	while (datalen--) {                 // could do this much faster, but it's short
81	    BufPut(m, BufGet(data));
82	}
83    }
84    BufHideRest(m);         // setup for the write by hiding the rest of the buffer
85    XTRACE(kPduConnect, 0, BufSize(m));     // check on it ...
86    // We do *not* free the input data buffer here
87NoMem:
88    return m;
89}
90
91// pull out parameter list from buffer returned from LMP connect indication
92// copies parameters to *plist, which better be at least 60 bytes long
93// "compacts" userdata in-place
94void
95ttp_pdu_connect_parse(
96    TTPBuf *data,               // input & output.  parameters stripped out
97    int *p,                     // output: p flag
98    int *n,                     // output: initial credit
99    unsigned char *plist)       // output parameter list (if any)
100{
101    unsigned char flag;
102
103    XTRACE(kPduConnectParse, 0, 0);
104
105    //BufSeekStart(data);       // should already be done for me
106    flag = BufGet(data);        // start parsing data buffer
107    BufHideStart(data, 1);      // remove it from client's view
108    *p = (flag >> 7) & 0x01;    // extract P flag
109    *n =  flag       & 0x7f;    // extract initial credit
110
111    if (*p) {                   // if flag set, parameters follow
112	int plen, i;
113	plen = BufGet(data);    // first byte of params in param length
114	BufHideStart(data, 1);          // remove it from client's view
115	if (plen > 60) return;  // sanity
116	*plist++ = plen;        // copy length to plist first
117	for (i = 0 ; i < plen; i++) {
118	    *plist++ = BufGet(data);    // copy to plist, assume big enough!
119	    BufHideStart(data, 1);          // remove it from client's view
120	}
121    }
122    else *plist = 0;            // just in case, tell caller it's zero len plist
123
124    XTRACE(kPduConnectParse, *p, *n);
125    // parameters should now be consumed out of the buffer
126}
127
128// searches the parameter list for one of type PiMaxSduSize
129// if not found, returns false
130// if found, sets *max with the value
131Boolean
132ttp_pdu_connect_get_max_sdu_size(unsigned char *plist, UInt32 *max)
133{
134    int plen;
135    UInt32  temp;
136    UInt32  pi;     // parameter type
137    UInt32  pl;     // parameter length
138    UInt32  i;
139
140    XTRACE(kPduGetMax, 0, *plist);
141
142    plen = *plist++;        // get length of entire param list
143    while (plen > 0) {      // loop over the thing
144	pi = *plist++;              // get parameter type
145	pl = *plist++;              // get parameter length
146	plen -= (2 + pl);           // subtract from total length
147	if (pi == PiMaxSduSize) {   // found what we're looking for??
148	    if (pl > sizeof(UInt32))            // sanity check
149		return false;                   // what to do here??
150	    temp = 0;
151	    for (i = 0; i < pl ; i++) {     // pull in the parameter
152		temp = temp << 8;
153		temp |= *plist++;
154	    }
155	    XTRACE(kPduGetMax, 1, temp);
156	    *max = temp;
157	    return true;
158	}
159    }       // loop over all parameters
160    return false;
161}
162
163//
164//  *** Data PDU
165//
166
167// Make a Data PDU for sending on to LMP
168// data can be nil if sending a dataless pdu for flow control
169//   ***** This needs to be REWRITTEN w/out a buffer copy!
170TTPBuf *
171ttp_pdu_data(Boolean m, int credit, TTPBuf *data)
172{   int len;
173    TTPBuf *outbuf;             // output TTPBuf
174    unsigned char byte;
175
176    XTRACE(kPduData, m, credit);
177
178    if (data) len = BufSize(data);      // current length of userdata
179    else      len = 0;
180    outbuf = BufAlloc(1 + len);     // make a new one with just the right size
181    require(outbuf, NoMem);
182
183    byte = credit & 0x7f;           // sanity check credit
184    if (m) byte |= 0x80;            // turn on more bit if needed
185    BufPut(outbuf, byte);           // set TTP overhead byte (overridden later)
186
187    if (len) {                      // if have data to copy
188	int count;
189	UInt8 *base;
190	base = BufBase(data);       // base of src buffer
191	check(base);
192
193	BufSeekStart(data);             // make sure mark is at front
194	count = outbuf->Putn(base, len);    // copy packet to new buffer
195	check(count == len);
196    }
197    BufHideRest(outbuf);            // this was missing!
198NoMem:
199    return outbuf;
200}
201
202// set the ttp overhead byte's value in the first byte of the data buffer
203void
204ttp_pdu_data_setbyte(Boolean m, int credit, TTPBuf *data)
205{
206    unsigned char byte;
207    unsigned char *wptr;
208
209    check(data);
210    byte = credit & 0x7f;           // sanity check credit
211    if (m) byte |= 0x80;            // turn on more bit if needed
212    wptr = BufBase(data);           // get the start of the buffer
213    check(wptr);
214    *wptr =byte;                    // zap the byte
215}
216
217
218
219// strips out ttp overhead byte
220void
221ttp_pdu_data_parse(TTPBuf *userData, Boolean *m, int *credit)
222{
223    unsigned char byte;
224    check(userData);
225
226    //XTRACE(kPduDataParse, 0, 0);
227				    // assumes rewound buffer
228    byte = BufGet(userData);        // grab the first byte please
229    BufHideStart(userData, 1);      // hide the first byte from the consumer
230    if (byte >> 7)  *m = true;      // more bit is on
231    else            *m = false;
232    *credit = (byte & 0x7f);        // delta credit
233    XTRACE(kPduDataParse, byte, BufSize(userData));
234}
235
236
237// this takes a (CBufferSegment) with mark at the end
238// of the valid data, hides from there to physical end
239// and rewinds the mark to the start of the buffer
240// this probably belongs elsewhere....
241// CBufferSegment assumed.
242void
243BufHideRest(TTPBuf *data)
244{   int size, length;
245
246    length = data->Position();
247    size = BufSize(data);       // get total amount of room in the buffer
248    check(size);
249
250    XTRACE (kBufferHideRest, 1, length);
251    XTRACE (kBufferHideRest, 2, size);
252
253    BufHideEnd(data, size-length);  // hide all but real data
254    BufSeekStart(data);             // move mark to start
255
256    XTRACE( kBufferHideRest, 3, BufSize(data));
257}
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272