Garmin Fleet Management Controller  2.19.0
GarminLinkLayer.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 *
3 * MODULE NAME:
4 * GarminLinkLayer.cpp
5 *
6 * Copyright 2008-2016 by Garmin Ltd. or its subsidiaries.
7 *---------------------------------------------------------------------
8 * $NoKeywords$
9 *********************************************************************/
10 
11 #include "stdafx.h"
12 #include "SerialPort.h"
13 #include "GarminLinkLayer.h"
14 #include "GarminPacket.h"
15 #include "Logger.h"
16 
18 
19 //----------------------------------------------------------------------
26 //----------------------------------------------------------------------
28 {
29  if( sInstance == NULL )
30  {
31  sInstance = new GarminLinkLayer();
33  }
34  return sInstance;
35 }
36 
37 //----------------------------------------------------------------------
39 //----------------------------------------------------------------------
41 {
42  delete sInstance;
43  sInstance = NULL;
44 }
45 
46 //----------------------------------------------------------------------
48 //----------------------------------------------------------------------
50 {
52  mFifo.head = 0;
53  mFifo.tail = 0;
54 
57 }
58 
59 //----------------------------------------------------------------------
63 //----------------------------------------------------------------------
65  (
66  PhysicalLayer * aPort
67  )
68 {
70  mFifo.head = 0;
71  mFifo.tail = 0;
72 
73  // Disconnect the existing physical layer
74  if( mPhysicalLayer != NULL )
75  {
77  SerialPort *mSerialPort = (SerialPort *) mPhysicalLayer;
78  delete mSerialPort;
79  mPhysicalLayer = NULL;
80  }
81 
82  setPhysicalLayer( aPort );
84 }
85 
86 //----------------------------------------------------------------------
92 //----------------------------------------------------------------------
94  (
95  uint8 const * const aData,
96  uint32 const aSize
97  )
98 {
99  /*----------------------------------------------------------
100  Local Variables
101  ----------------------------------------------------------*/
102  uint8 *ptr;
103  uint32 i;
104 
105 
106  ptr = (uint8 *)aData;
107 
108  for( i = 0; i < aSize; i++ )
109  {
110  mFifo.buffer[ mFifo.tail ] = ptr[ i ];
111  mFifo.tail = ( mFifo.tail >= ( mFifo.size - 1 ) ) ? 0 : mFifo.tail + 1;
112  }
113 
114  // now frame the packets
115  while( getPacketFromFifo() );
116 } /* rx() */
117 
118 //----------------------------------------------------------------------
123 //----------------------------------------------------------------------
125 {
126  if( mFifo.tail >= mFifo.head )
127  {
128  return( mFifo.tail - mFifo.head );
129  }
130  else
131  {
132  return( ( mFifo.size - mFifo.head ) + mFifo.tail );
133  }
134 } /* numBytesInFifo() */
135 
136 //----------------------------------------------------------------------
154 //----------------------------------------------------------------------
156 {
157  /*----------------------------------------------------------
158  Local Variables
159  ----------------------------------------------------------*/
160  uint32 fifoSize;
161  header_type header;
162  footer_type footer;
163  uint32 prevHead;
164  uint32 payloadStart;
165  uint32 payloadEnd;
166  uint8 checksum;
167  uint8 *ptr;
168  GarminPacket *packet;
169 
170  //loop until Garmin back found or FIFO empty
171  while( mFifo.head != mFifo.tail )
172  {
173  prevHead = mFifo.head;
174  fifoSize = numBytesInFifo();
175  if( fifoSize < MIN_PACKET_SIZE ) return false;
176 
177  getDataFromFifo( (uint8 *)&header, SIZE_OF_HEADER );
178 
179  //find header
180  if( ( header.dle != ID_DLE_BYTE ) ||
181  ( header.id == ID_ETX_BYTE ) )
182  {
183  incrementHead( 1 );
184  continue;
185  }
186  //find footer
188  payloadStart = mFifo.head;
189  payloadEnd = payloadStart;
190  while( mFifo.head != mFifo.tail )
191  {
192  fifoSize = numBytesInFifo();
193  if( fifoSize < SIZE_OF_FOOTER )
194  {
195  break;
196  }
197 
198  getDataFromFifo( (uint8*)&footer, SIZE_OF_FOOTER );
199  if( ( footer.dle == ID_DLE_BYTE ) &&
200  ( footer.etx == ID_DLE_BYTE ) )
201  {
202  incrementHead( 2 );
203  }
204  else if( ( footer.dle == ID_DLE_BYTE ) &&
205  ( footer.etx == ID_ETX_BYTE ) )
206  {
207  payloadEnd = mFifo.head;
208  break;
209  }
210  else
211  incrementHead( 1 );
212  }
213  //if footer not found, entire packet not received yet
214  if( payloadStart == payloadEnd )
215  {
216  mFifo.head = prevHead;
217  return false;
218  }
219 
220  //complete packet exists in receive queue
221  packet = new GarminPacket;
222  mFifo.head = payloadStart;
223  packet->mPacketId = header.id;
224  packet->mPayloadSize = header.size;
225  if( packet->mPayloadSize == ID_DLE_BYTE )
226  {
227  incrementHead( 1 );
228  }
229  packet->mFrameSize = 0;
230  packet->mChecksum = ( header.id + header.size ) % 256;
231 
232  ptr = (uint8*)packet->mPayload;
233 
234  while( ( mFifo.head != payloadEnd )
235  && ( packet->mFrameSize < packet->mPayloadSize ) )
236  {
237  getDataFromFifo( (uint8*)&ptr[packet->mFrameSize], 2 );
238  packet->mChecksum = ( ptr[ packet->mFrameSize] + packet->mChecksum ) % 256;
239  incrementHead( 1 );
240  if( ( ptr[ packet->mFrameSize ] == ID_DLE_BYTE ) &&
241  ( ptr[ packet->mFrameSize + 1 ] == ID_DLE_BYTE ) )
242  incrementHead( 1 );
243  packet->mFrameSize++;
244  }
245 
246  getDataFromFifo( (uint8*)&checksum, 1 );
247  packet->mChecksum = ( checksum + packet->mChecksum ) % 256;
248  if( checksum == ID_DLE_BYTE )
249  {
250  incrementHead( 2 );
251  }
252  else
253  {
254  incrementHead( 1 );
255  }
256 
257  packet->mFrameSize = 0;
258  uint32 endOfFrame = (mFifo.head + SIZE_OF_FOOTER) % FIFO_SIZE;
259  while( prevHead != endOfFrame )
260  {
261  packet->mFrame[packet->mFrameSize++] = mFifo.buffer[prevHead];
262  //increment prevHead and wrap around to 0 if goes past FIFO boundaries
263  prevHead = ( prevHead >= ( mFifo.size - 1 ) ) ? 0 : prevHead + 1;
264  }
265 
266  Logger::logRawData( packet, FALSE );
267  // checksum is 2's complement of sum of all the data...we calculated checksum
268  // as just the sum, so if we add them together they should be zero
269  if( packet->mChecksum != 0 )
270  {
271  // Invalid checksum; send NAK and keep looking for a packet.
272  if( mTransportLayer )
273  {
274  uint8 payload[2] = { packet->mPacketId, 0 };
276  (
277  new GarminPacket( ID_NAK_BYTE, payload, sizeof( payload ) ),
278  TRUE
279  );
280  }
281  delete packet;
282  mFifo.head = payloadStart;
283  continue;
284  }
285  else
286  {
287  if( mTransportLayer )
288  {
289  // Send ACK (if required) and push the packet up the stack for processing.
290  // ACK and NAK packets must not be ACKed.
291  if( packet->mPacketId != ID_ACK_BYTE &&
292  packet->mPacketId != ID_NAK_BYTE )
293  {
294  uint8 payload[2] = { packet->mPacketId, 0 };
295  mTransportLayer->tx( new GarminPacket( ID_ACK_BYTE, payload, sizeof( payload ) ), TRUE );
296  }
297  mTransportLayer->rx( packet );
298  }
299  delete packet;
300  }
302  return true;
303  }
304  return false;
305 } /* getPacketFromFifo */
306 
307 //----------------------------------------------------------------------
316 //----------------------------------------------------------------------
318  (
319  uint8 * aData,
320  uint32 aSize
321  )
322 {
323  /*----------------------------------------------------------
324  Local Variables
325  ----------------------------------------------------------*/
326  int wrapSize;
327 
328  if( ( mFifo.head + aSize ) < mFifo.size )
329  {
330  memcpy( &aData[0], &mFifo.buffer[mFifo.head], aSize );
331  }
332  else
333  {
334  wrapSize = mFifo.size - mFifo.head;
335  memmove( &aData[0], &mFifo.buffer[mFifo.head], wrapSize );
336  memmove( &aData[ wrapSize ], &mFifo.buffer[0], aSize - wrapSize );
337  }
338 } /* getDataFromFifo() */
339 
340 //----------------------------------------------------------------------
347 //----------------------------------------------------------------------
349  (
350  uint32 const aIncrement
351  )
352 {
353  /*----------------------------------------------------------
354  Local Variables
355  ----------------------------------------------------------*/
356  uint32 i;
357 
358  i = mFifo.head + aIncrement;
359 
360  if( mFifo.tail > mFifo.head )
361  {
362  if( i <= mFifo.tail )
363  {
364  mFifo.head = i;
365  }
366  else
367  {
368  mFifo.head = mFifo.tail;
369  }
370  }
371  else if( mFifo.tail < mFifo.head )
372  {
373  if( i < mFifo.size )
374  {
375  mFifo.head = i;
376  }
377  else
378  {
379  i -= mFifo.size;
380  if( i<mFifo.tail )
381  {
382  mFifo.head = i;
383  }
384  else
385  {
386  mFifo.head = mFifo.tail;
387  }
388  }
389  }
390 } /* incrementHead() */
391 
392 //----------------------------------------------------------------------
398 //----------------------------------------------------------------------
400  (
401  Packet * aPacket
402  )
403 {
404  GarminPacket * thePacket = dynamic_cast<GarminPacket *>( aPacket );
405 
406  ASSERT( thePacket != NULL );
407 
408  uint8 i;
409  thePacket->mFrameSize = 0;
410 
411  // Frame header (DLE)
412  thePacket->mFrame[ thePacket->mFrameSize++ ] = ID_DLE_BYTE;
413 
414  // Packet ID
415  thePacket->mFrame[ thePacket->mFrameSize++ ] = thePacket->mPacketId;
416 
417  // Payload size, DLE stuffing if necessary
418  thePacket->mFrame[ thePacket->mFrameSize++ ] = thePacket->mPayloadSize;
419  if( thePacket->mPayloadSize == ID_DLE_BYTE )
420  {
421  thePacket->mFrame[ thePacket->mFrameSize++ ] = thePacket->mPayloadSize;
422  }
423 
424  // Payload, DLE stuffing as necessary
425  for( i = 0; i < thePacket->mPayloadSize; i++)
426  {
427  thePacket->mFrame[ thePacket->mFrameSize++ ] = thePacket->mPayload[i];
428  if( thePacket->mPayload[i] == ID_DLE_BYTE )
429  {
430  thePacket->mFrame[ thePacket->mFrameSize++ ] = thePacket->mPayload[i];
431  }
432  }
433 
434  // Checksum, DLE stuffing if necessary
435  thePacket->mFrame[ thePacket->mFrameSize++ ] = thePacket->mChecksum;
436  if( thePacket->mChecksum == ID_DLE_BYTE )
437  {
438  thePacket->mFrame[ thePacket->mFrameSize++ ] = thePacket->mChecksum;
439  }
440 
441  // Frame footer (DLE and ETX bytes)
442  thePacket->mFrame[ thePacket->mFrameSize++ ] = ID_DLE_BYTE;
443  thePacket->mFrame[ thePacket->mFrameSize++ ] = ID_ETX_BYTE;
444 
445  Logger::logRawData( thePacket );
446 
447  return mPhysicalLayer->tx( thePacket->mFrame, thePacket->mFrameSize );
448 }
Abstract base class for the physical layer.
Definition: PhysicalLayer.h:25
virtual void rx(uint8 const *const aData, uint32 const aSize)
Copy Data to FIFO.
#define MIN_PACKET_SIZE
Minimum packet size: DLE + Packet ID + Payload Size + Data + Checksum + DLE + ETX.
Definition: garmin_types.h:18
uint8 mFrame[MAX_PACKET_SIZE]
The packet as transmitted on the serial link (with DLE stuffing)
Definition: GarminPacket.h:50
int numBytesInFifo()
Calculate the number of bytes in the FIFO buffer.
#define SIZE_OF_FOOTER
Size of packet footer (after payload and checksum)
Definition: garmin_types.h:37
Garmin serial packet.
Definition: GarminPacket.h:26
GarminLinkLayer()
Construct a new GarminLinkLayer.
virtual bool tx(uint8 *aData, uint16 aSize)=0
Transmit data.
uint32 head
Index of first byte of data.
uint8 mChecksum
Twos-complement checksum of this packet.
Definition: GarminPacket.h:48
uint8 size
Size of payload.
Definition: garmin_types.h:108
static GarminLinkLayer * getInstance()
Get the one and only link layer object.
bool getPacketFromFifo()
Frame Packet.
#define FALSE
Definition: garmin_types.h:46
uint8 buffer[FIFO_SIZE]
Data buffer.
virtual void rx(Packet *aPacket)=0
Callback when a complete packet is assembled by the LinkLayer.
#define TRUE
Definition: garmin_types.h:45
#define SIZE_OF_HEADER
Size of packet header, before DLE stuffing.
Definition: garmin_types.h:34
fifo_type mFifo
FIFO (First-In, First-Out) buffer used to store bytes received from the client until they are parsed ...
#define ID_ETX_BYTE
Definition: garmin_types.h:39
void resetPhysicalLayer(PhysicalLayer *aPort)
Reset the physical layer.
uint8 dle
DLE byte.
Definition: garmin_types.h:106
PhysicalLayer * mPhysicalLayer
The serial port that this link layer communicates with.
Definition: LinkLayer.h:74
void incrementHead(uint32 aIncrement)
Increment FIFO head.
uint8 etx
ETX byte.
Definition: garmin_types.h:115
static SerialPort * getInstance()
Get the one and only serial port object.
Definition: SerialPort.cpp:36
uint8 mPayload[MAX_PAYLOAD_SIZE]
The payload, before DLE stuffing.
Definition: GarminPacket.h:49
uint8 dle
DLE byte.
Definition: garmin_types.h:114
#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 tx(Packet *aPacket, bool aSendNow)=0
Transmit a packet.
void getDataFromFifo(uint8 *aData, uint32 aSize)
Get Data From FIFO.
uint16 mFrameSize
Number of bytes in the packet, with header, footer, and DLE stuffing.
Definition: GarminPacket.h:47
uint32 tail
Index of last byte of data.
virtual void setLinkLayer(LinkLayer *aLinkLayer)
Change the link layer that receives bytes from this SerialPort.
TransportLayer * mTransportLayer
The transport layer that this link layer communicates with.
Definition: LinkLayer.h:77
unsigned char uint8
8-bit unsigned integer
Definition: garmin_types.h:62
void setPhysicalLayer(PhysicalLayer *aPort)
Set the physical layer.
Definition: LinkLayer.cpp:41
static GarminLinkLayer * sInstance
The one and only instance of this class.
uint8 mPayloadSize
Size of the payload, before DLE stuffing.
Definition: GarminPacket.h:46
uint32 size
Number of bytes of data in the buffer.
The packet header (the bytes before the payload)
Definition: garmin_types.h:104
uint8 id
Garmin packet ID.
Definition: garmin_types.h:107
Link Layer in the OSI model.
static void logRawData(Packet *aPacket, bool aIsTx=true)
Logs the raw data of the packet passed in to a file.
Definition: Logger.cpp:31
#define FIFO_SIZE
The size of the server&#39;s internal FIFO buffer for parsing raw data into packets for processing...
unsigned long int uint32
32-bit unsigned integer
Definition: garmin_types.h:66
static void destroyInstance()
Delete the one and only link layer object.
Physical layer implementation for a serial port.
Definition: SerialPort.h:30
#define ID_ACK_BYTE
Definition: garmin_types.h:40
#define ID_DLE_BYTE
Definition: garmin_types.h:41
virtual bool tx(Packet *aPacket)
Transmit a packet.
The packet footer (the bytes after the payload and checksum)
Definition: garmin_types.h:112