Garmin Fleet Management Controller  2.19.0
GarminTransportLayer.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 *
3 * MODULE NAME:
4 * GarminTransportLayer.cpp
5 *
6 * Copyright 2008-2009 by Garmin Ltd. or its subsidiaries.
7 *---------------------------------------------------------------------
8 * $NoKeywords$
9 *********************************************************************/
10 
11 #include "stdafx.h"
12 #include "GarminTransportLayer.h"
13 #include "Event.h"
14 #include "Logger.h"
15 
16 #define COM_TIMEOUT 3
17 
19 
20 //----------------------------------------------------------------------
25 //----------------------------------------------------------------------
27 {
28  if( sInstance == NULL )
29  {
32  }
33  return sInstance;
34 }
35 
36 //----------------------------------------------------------------------
38 //----------------------------------------------------------------------
40 {
41  delete sInstance;
42  sInstance = NULL;
43 }
44 
45 //----------------------------------------------------------------------
47 //----------------------------------------------------------------------
50  , mLastAckSent( NULL )
51  , mLastNakSent( NULL )
52 {
53  mCommError = false;
55 }
56 
57 //----------------------------------------------------------------------
60 //----------------------------------------------------------------------
62 {
63  if( mLinkLayer )
64  {
66  }
67 
68  while( mAppLayers.size() > 0 )
69  {
70  mAppLayers.front()->disconnectTransportLayer();
71  mAppLayers.pop_front();
72  }
73 
74  while( !mTransmitQueue.empty() )
75  {
76  const GarminPacket * packet = mTransmitQueue.front();
77  mTransmitQueue.pop_front();
78  delete packet;
79  }
80 
81  if( NULL != mLastAckSent )
82  {
83  delete mLastAckSent;
84  mLastAckSent = NULL;
85  }
86 
87  if( NULL != mLastNakSent )
88  {
89  delete mLastNakSent;
90  mLastNakSent = NULL;
91  }
92 }
93 //----------------------------------------------------------------------
102 //----------------------------------------------------------------------
104  (
105  Packet * aPacket
106  )
107 {
108  GarminPacket * thePacket = dynamic_cast<GarminPacket *>( aPacket );
109  ASSERT( thePacket != NULL );
110  ASSERT( mAppLayers.size() != 0 );
111 
112  // Handle the packet that was received.
113  switch( thePacket->mPacketId )
114  {
115  case ID_ACK_BYTE:
116  {
117  //packet was received at client, remove from queue
118  //and send the next (if there was one)
119  if( !mTransmitQueue.empty() )
120  {
121  const GarminPacket * packet = mTransmitQueue.front();
122 
123  if( packet->mSender != NULL )
124  packet->mSender->onAck( packet );
125 
126  mTransmitQueue.pop_front();
127  delete packet;
128  }
129  if( !mTransmitQueue.empty() )
130  sendPacket();
131  break;
132  }
133  case ID_NAK_BYTE:
134  {
135  // A received NAK indicates a communication error in the link.
136  // However, ACK and NAK packets are not maintained in the transmit
137  // queue. If we receive a NAK for one of these packets, we should
138  // send the correct packet back. If we receive a NAK for the most
139  // recent data packet, i.e. the one waiting for an ACK, then we
140  // should resend that packet. Otherwise, do nothing, because the
141  // NAK that we received is malformed.
142 
143  if( ID_ACK_BYTE == thePacket->mPayload[0] && NULL != mLastAckSent )
144  {
145  // Send the most recent ACK.
146  mTransmitQueue.push_front(mLastAckSent);
147  sendPacket();
148  mTransmitQueue.pop_front();
149  }
150  else if( ID_NAK_BYTE == thePacket->mPayload[0] && NULL != mLastNakSent )
151  {
152  // Send the most recent NAK.
153  mTransmitQueue.push_front(mLastNakSent);
154  sendPacket();
155  mTransmitQueue.pop_front();
156  }
157  else if( !mTransmitQueue.empty() &&
158  mTransmitQueue.front()->mPacketId == thePacket->mPayload[0] )
159  {
160  // Send a data packet only if there is an unacknowledged data
161  // packet with a matching Packet ID field.
162  sendPacket();
163  }
164 
165  break;
166  }
167  default:
168  {
169  // All other packets are sent to the app layer for processing.
170  AppLayerList::iterator iter;
171  for( iter = mAppLayers.begin(); iter != mAppLayers.end(); iter++ )
172  {
173  if( (*iter)->rx( thePacket ) )
174  break;
175  }
176  }
177  }
178 }
179 
180 //----------------------------------------------------------------------
191 //----------------------------------------------------------------------
193 {
194  if( !mCommError && !mTransmitQueue.empty() )
195  {
196  time_t currentTime;
197  double elapsed;
198 
199  time( &currentTime );
200  elapsed = difftime( currentTime, mTransmitQueue.front()->mTxTime );
201  if( elapsed > COM_TIMEOUT )
202  {
204  mCommError = true;
205  }
206  }
207 }
208 
209 //----------------------------------------------------------------------
211 //----------------------------------------------------------------------
213 {
214  mCommError = false;
215  sendPacket();
216 }
217 
218 //----------------------------------------------------------------------
233 //----------------------------------------------------------------------
235  (
236  Packet * aPacket,
237  bool aSendNow
238  )
239 {
240  GarminPacket * packet = dynamic_cast<GarminPacket *>( aPacket );
241 
242  ASSERT( packet != NULL );
243 
244  /*----------------------------------------------------------
245  Local Variables
246  ----------------------------------------------------------*/
247  int i;
248 
249  packet->mChecksum = ( packet->mPacketId + packet->mPayloadSize ) & 0xFF;
250 
251  //calculate rest of checksum
252  for( i = 0; i < packet->mPayloadSize; i++ )
253  {
254  packet->mChecksum = ( packet->mPayload[i] + packet->mChecksum ) & 0xFF;
255  }
256 
257  //the checksum is the 2's complement of all the data
258  //in the packet
259  packet->mChecksum = ( ( packet->mChecksum ^ 0xFF ) + 1 ) & 0xFF;
260 
261  if( aSendNow || mTransmitQueue.empty() )
262  {
263  mTransmitQueue.push_front( packet );
264  if( !mCommError )
265  {
266  bool result;
267  result = sendPacket();
268  if( result )
269  {
270  if( packet->mPacketId == ID_ACK_BYTE ||
271  packet->mPacketId == ID_NAK_BYTE )
272  {
273  mTransmitQueue.pop_front();
274  delete packet;
275  }
276  }
277  }
278  }
279  else
280  {
281  mTransmitQueue.push_back( packet );
282  }
283  return;
284 }
285 
286 //----------------------------------------------------------------------
295 //----------------------------------------------------------------------
297 {
298  ASSERT( !mTransmitQueue.empty() );
299 
300  GarminPacket *packet = mTransmitQueue.front();
301 
302  // Retain a copy if this packet is an ACK.
303  if( ID_ACK_BYTE == packet->mPacketId )
304  {
305  // If this is the first ACK, then allocate memory.
306  if( NULL == mLastAckSent )
307  {
308  mLastAckSent = new GarminPacket();
309  }
310 
311  // Copy the packet contents.
312  *mLastAckSent = *packet;
313  }
314  // Retain a copy if this packet is a NAK.
315  else if( ID_NAK_BYTE == packet->mPacketId )
316  {
317  // If this is the first NAK, then allocate memory.
318  if( NULL == mLastNakSent )
319  {
320  mLastNakSent = new GarminPacket();
321  }
322 
323  // Copy the packet contents.
324  *mLastNakSent = *packet;
325  }
326 
327  time( &packet->mTxTime );
328 
329  return mLinkLayer->tx( packet );
330 }
virtual void tx(Packet *aPacket, bool aSendImmediate)
Transmit a Packet.
static GarminTransportLayer * sInstance
The one and only instance of this class.
void rx(Packet *aPacket)
Packet receive callback.
ApplicationLayer * mSender
The ApplicationLayer that originated this packet (for ACK callback)
Definition: GarminPacket.h:51
bool mCommError
If true, a communication error has occurred (transmit is suspended)
PacketList mTransmitQueue
Queue of packets being transmitted; the head of the queue may have been sent but is not ACKed...
static void destroyInstance()
Delete the one and only GarminTransportLayer instance.
Garmin serial packet.
Definition: GarminPacket.h:26
virtual void onTimer()
Periodic callback.
uint8 mChecksum
Twos-complement checksum of this packet.
Definition: GarminPacket.h:48
virtual void onAck(const Packet *aPacket)=0
Callback when a sent packet is ACKed.
bool sendPacket()
Send a Packet.
GarminPacket * mLastNakSent
A copy of the most recently sent NAK.
uint8 mPayload[MAX_PAYLOAD_SIZE]
The payload, before DLE stuffing.
Definition: GarminPacket.h:49
virtual ~GarminTransportLayer()
GarminTransportLayer destructor.
void setTransportLayer(TransportLayer *aTransport)
Set the transport layer.
Definition: LinkLayer.cpp:55
#define ID_NAK_BYTE
Definition: garmin_types.h:42
id_type mPacketId
A complete serial packet.
Definition: GarminPacket.h:44
Abstract base class for a packet of data.
Definition: Packet.h:18
virtual void retry()
Tries to resend the most recently sent packet.
AppLayerList mAppLayers
The application layer objects that send/receive using this GarminTransportLayer.
GarminLinkLayer * mLinkLayer
The link layer that frames are sent/received from.
Transport layer in the OSI communication model.
#define COM_TIMEOUT
timeout in seconds
uint8 mPayloadSize
Size of the payload, before DLE stuffing.
Definition: GarminPacket.h:46
GarminTransportLayer()
Construct a GarminTransportLayer.
Link Layer in the OSI model.
GarminPacket * mLastAckSent
A copy of the most recently sent ACK.
#define ID_ACK_BYTE
Definition: garmin_types.h:40
virtual bool tx(Packet *aPacket)
Transmit a packet.
static GarminTransportLayer * getInstance()
Get the one and only GarminTransportLayer.
static void post(EventId aEventId, uint32 aEventData=0, void *aEventDataPtr=NULL, BOOL handleNow=FALSE)
Posts a message to all windows that have registered to get events.
Definition: Event.cpp:67