#include "ttp.h"
#include "ttppdu.h"
#include "CBufferSegment.h"
#include "IrDALog.h"
#if (hasTracing > 0 && hasTTPTracing > 0)
enum IrTinyTPTraceCodes
{
kLogFree = 1,
kLogInit,
kDiscoverRequest,
kLookupRequest,
kListenRequest,
kConnectRequest,
kConnectResponse,
kDisconnectRequest,
kDataRequest,
kFlowControl,
kDataRequestDropped,
kXmitQueueSize,
kXmitQueueSize2,
kXmitQueueSize3,
kXmitIrDABufsLow,
kTTPRxDone,
kDiscardPendingPuts
};
EventTraceCauseDesc gTraceEvents[] = {
{kLogFree, "TinyTP: free obj="},
{kLogInit, "TinyTP: initializing, obj=, credit=, lsap="},
{kDiscoverRequest, "TinyTP: discover request"},
{kLookupRequest, "TinyTP: lookup request"},
{kListenRequest, "TinyTP: listen request"},
{kConnectRequest, "TinyTP: connect request"},
{kConnectResponse, "TinyTP: connect response"},
{kDisconnectRequest, "TinyTP: disconnect request"},
{kDataRequest, "TinyTP: put data request"},
{kFlowControl, "TinyTP: flow control request"},
{kDataRequestDropped, "TinyTP: ** Data request dropped ***"},
{kXmitQueueSize, "TinyTP: XMIT Queue Size, sendcredit=, depth="},
{kXmitQueueSize2, "TinyTP: XMIT Queue Size2, explode_factor, MaxSegSize="},
{kXmitQueueSize3, "TinyTP: XMIT Queue Size3, txQDepth=, depth="},
{kXmitIrDABufsLow, "TinyTP: XMIT - global buffers low, SendCredit=, CBufCnt="},
{kTTPRxDone, "TinyTP: Client says Rx is done"},
{kDiscardPendingPuts, "TinyTP: discard pending puts"}
};
#define XTRACE(x, y, z) IrDALogAdd( x, y, (uintptr_t)z & 0xffff, gTraceEvents, true )
#else
#define XTRACE(x, y, z) ((void)0)
#endif
const UInt8 kIASTinyTPLSAPSelAttrStr[] = "IrDA:TinyTP:LsapSel";
#define super CIrLSAP
OSDefineMetaClassAndAbstractStructors(TTinyTP, CIrLSAP);
void
TTinyTP::free()
{
XTRACE(kLogFree, 0, this);
super::free();
}
Boolean
TTinyTP::TTPInitialize( TIrGlue *irda, UInt32 credit, UInt32 desiredLSAPId, UInt8 * className, ULong hints)
{
int i;
XTRACE(kLogInit, 0, this);
XTRACE(kLogInit, credit, desiredLSAPId);
TxQueue.qFlags = 0;
TxQueue.qHead = TxQueue.qTail = nil;
RxQueue.qFlags = 0;
RxQueue.qHead = RxQueue.qTail = nil;
AvailQueue.qFlags = 0;
AvailQueue.qHead = AvailQueue.qTail = nil;
AvailCredit = 0; RemoteCredit = 0;
SendCredit = 0;
MaxSegSize = 0;
TxMaxSduSize = 0;
RxMaxSduSize = 0;
RxSdu.sarbuf = nil;
RxSdu.busy = false;
txQDepth = 0; Connected = false;
discoverPending = false;
initial_credit = credit;
for (i = 0 ; i < kMaxTTPRequests ; i++) {
TTPq *tq;
tq = &ttpqpool[i]; tq->qLink = nil;
tq->qType = 1;
Enqueue((QElem *)tq, &(this->AvailQueue)); }
return super::Init(irda, desiredLSAPId, className, (UInt8 *) kIASTinyTPLSAPSelAttrStr, hints); }
void
TTinyTP::DoDiscoverRequest (int slots)
{
XTRACE(kDiscoverRequest, 0, this);
if (!discoverPending) {
discoverPending = true;
this->Discover(slots); }
}
void
TTinyTP::DoLookupRequest (
unsigned char *classname,
UInt32 remoteAddr ) {
XTRACE(kLookupRequest, 0, this);
this->LSAPLookup(classname, ( UInt8 * )kIASTinyTPLSAPSelAttrStr, remoteAddr );
}
void
TTinyTP::DoListenRequest(
TTPBuf *userData) {
XTRACE(kListenRequest, 0, this);
Listen(userData); }
void
TTinyTP::DoConnectRequest (
UInt32 remoteAddr, TTPSAP sap, TIrQOS *qos, int maxSduSize,
TTPBuf *userData) {
#pragma unused (qos)
int n;
TTPBuf *pduBuf;
XTRACE(kConnectRequest, 0, this);
fPeerAddr = remoteAddr; fPeerSAP = sap;
this->Connected = false; this->AvailCredit = 0; this->RxMaxSduSize = maxSduSize; this->RxSdu.sarbuf = nil; this->RxSdu.busy = false;
n = this->initial_credit; this->SendCredit = 0;
if (n > 127) {
AvailCredit = n - 127;
n = 127;
}
RemoteCredit = n;
pduBuf = ttp_pdu_connect ( (maxSduSize == 0) ? 0 : 1, n, maxSduSize, userData);
require(pduBuf, NoMem);
this->Connect(fPeerAddr, sap, pduBuf); this->CheckTheQueues();
NoMem:
return;
}
void
TTinyTP::DoConnectResponse (
TTPSAP sap, int maxSduSize, TTPBuf *userData) {
#pragma unused (sap)
int n;
TTPBuf *pduBuf;
XTRACE(kConnectResponse, 0, this);
XTRACE(kConnectResponse, sap, maxSduSize);
XTRACE(kConnectResponse, maxSduSize >> 16, maxSduSize);
this->AvailCredit = 0;
this->RxMaxSduSize = maxSduSize;
this->RxSdu.sarbuf = nil; this->RxSdu.busy = false;
n = this->initial_credit; if (n > 127) {
this->AvailCredit = n - 127;
n = 127;
}
this->RemoteCredit = n; pduBuf = ttp_pdu_connect(
(maxSduSize == 0) ? 0 : 1, n, maxSduSize, userData);
require(pduBuf, NoMem);
this->Accept(pduBuf); this->Connected = true;
this->CheckTheQueues(); NoMem:
return;
}
void
TTinyTP::DoDisconnectRequest (
TTPBuf *userData) {
XTRACE(kDisconnectRequest, 0, this);
if (Connected == false) { Disconnect(); }
else {
this->AppendTail(&(this->TxQueue), TTP_Disconnect, 0, userData);
txQDepth++;
this->CheckTheQueues(); }
}
extern int queueDepth(QHdr *qh);
void
TTinyTP::DoDataRequest (
TTPBuf *userData) {
TTPBuf *newbuf;
XTRACE(kDataRequest, 0, this);
check (userData); if (!userData) return;
check(BufSize(userData)); if (Connected == false) return;
if (this->TxMaxSduSize == 0) { if (BufSize(userData) > this->MaxSegSize)
return; newbuf = ttp_pdu_data(false, 0, userData);
require(newbuf, NoMem);
this->AppendTail(&(this->TxQueue), TTP_Segment_Last, 0, newbuf);
txQDepth++;
}
else { int i, numsegs;
if (BufSize(userData) > this->TxMaxSduSize) return;
numsegs = ((BufSize(userData) + this->MaxSegSize -1) / this->MaxSegSize);
if (numsegs == 1) { newbuf = ttp_pdu_data(false, 0, userData); require(newbuf, NoMem);
this->AppendTail(&(this->TxQueue), TTP_Segment_Last, 0, newbuf);
txQDepth++;
}
else { TTPBuf *seg; for (i = 1 ; i < numsegs; i++) { seg = GetSegment(i, userData); require(seg, NoMem);
newbuf = ttp_pdu_data(true, 0, seg); require(newbuf, NoMem);
BufFree(seg); this->AppendTail(&(this->TxQueue), TTP_Segment, 0, newbuf);
txQDepth++;
}
seg = GetSegment(numsegs, userData); require(seg, NoMem);
newbuf = ttp_pdu_data(false, 0, seg); require(newbuf, NoMem);
BufFree(seg); this->AppendTail(&(this->TxQueue), TTP_Segment_Last, 0, newbuf);
txQDepth++;
}
}
this->CheckTheQueues(); NoMem:
return;
}
void
TTinyTP::TTPDiscardPendingPuts(void)
{
TTPq *tq;
IrDAErr err;
int counter = 0;
XTRACE(kDiscardPendingPuts, 0x1111, 0);
while ((tq = (TTPq *)TxQueue.qHead) != 0) {
if (tq->qType != TTP_Segment && tq->qType != TTP_Segment_Last) break; err = Dequeue((QElem *)tq, &TxQueue);
ncheck(err); if (tq->buf != 0) BufFree(tq->buf); tq->buf = nil;
tq->qLink = nil;
Enqueue((QElem *)tq, &AvailQueue);
counter++;
}
XTRACE(kDiscardPendingPuts, 0xffff, counter);
}
void
TTinyTP::DoUdataRequest ( TTPBuf *userData) {
#pragma unused (userData)
if (this->Connected == false) return; }
void
TTinyTP::SetLocalFlow (
TFlowOnOff onOff) {
XTRACE(kFlowControl, 0, 0);
if (onOff == FlowOn) this->RxSdu.busy = false;
else this->RxSdu.busy = true;
this->CheckTheQueues(); }
int
TTinyTP::TTPXmitQueueSize(int maxPacketSize)
{ int depth;
int explode_factor;
depth = SendCredit;
depth -= txQDepth;
XTRACE(kXmitQueueSize3, txQDepth, depth);
check(depth >= 0); if (depth <= 0) return 0;
if (this->TxMaxSduSize == 0) { XTRACE(kXmitQueueSize, SendCredit, depth);
return depth; }
explode_factor = (maxPacketSize + this->MaxSegSize -1) / this->MaxSegSize;
depth = depth / explode_factor;
if (depth == 0) { depth = 1; }
XTRACE(kXmitQueueSize, SendCredit, depth);
XTRACE(kXmitQueueSize2, explode_factor, MaxSegSize);
return depth; }
void
TTinyTP::TTPRxDone(void) {
AvailCredit++; XTRACE(kTTPRxDone, RemoteCredit, AvailCredit);
CheckTheQueues(); }