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