sbgEComTransfer.c
Go to the documentation of this file.
1 #include "sbgEComTransfer.h"
2 #include "../sbgEComCmdCommon.h"
5 
6 //----------------------------------------------------------------------//
7 //- Internal transfer method definitions -//
8 //----------------------------------------------------------------------//
9 
18 static SbgErrorCode sbgEComTransferSendInit(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, size_t size)
19 {
20  SbgErrorCode errorCode = SBG_NO_ERROR;
21  SbgStreamBuffer streamBuffer;
22  uint8_t outputBuffer[SBG_ECOM_MAX_PAYLOAD_SIZE];
23  uint32_t i;
24 
25  assert(pHandle);
26 
27  //
28  // Initialize stream buffer that will contain payload
29  //
30  sbgStreamBufferInitForWrite(&streamBuffer, outputBuffer, sizeof(outputBuffer));
31 
32  //
33  // Build transfer payload (a SBG_ECOM_TRANSFER_START command and the total size of the upload)
34  //
36  sbgStreamBufferWriteSizeT32LE(&streamBuffer, size);
37 
38  //
39  // Send command (multiple times in case of failures)
40  //
41  for (i = 0; i < 3; i++)
42  {
43  //
44  // Send transfer payload encapsulated in ECom protocol
45  //
46  errorCode = sbgEComProtocolSend(&pHandle->protocolHandle, msgClass, msg, sbgStreamBufferGetLinkedBuffer(&streamBuffer), sbgStreamBufferGetLength(&streamBuffer));
47 
48  if (errorCode == SBG_NO_ERROR)
49  {
50  //
51  // If the device accepts the transfer, it returns an ack, wait for the answer.
52  //
53  errorCode = sbgEComWaitForAck(pHandle, msgClass, msg, pHandle->cmdDefaultTimeOut);
54 
55  //
56  // Test if the response is positive from device
57  //
58  if (errorCode == SBG_NO_ERROR)
59  {
60  //
61  // Ack received, no need for other trial.
62  //
63  break;
64  }
65  }
66  }
67 
68  return errorCode;
69 }
70 
81 static SbgErrorCode sbgEComTransferSendData(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, const void *pBuffer, size_t offset, size_t packetSize)
82 {
83  SbgErrorCode errorCode = SBG_NO_ERROR;
84  SbgStreamBuffer streamBuffer;
85  uint8_t outputBuffer[SBG_ECOM_MAX_PAYLOAD_SIZE];
86  uint32_t i;
87 
88  assert(pHandle);
89  assert(pBuffer);
90  assert(packetSize > 0);
91 
92  //
93  // Initialize stream buffer for output
94  //
95  sbgStreamBufferInitForWrite(&streamBuffer, outputBuffer, sizeof(outputBuffer));
96 
97  //
98  // Build payload: a SBG_ECOM_TRANSFER_DATA command, the offset from the start of the transfer, and the data
99  //
101  sbgStreamBufferWriteSizeT32LE(&streamBuffer, offset);
102  sbgStreamBufferWriteBuffer(&streamBuffer, pBuffer, packetSize);
103 
104  //
105  // Send command (multiple times in case of failures)
106  //
107  for (i = 0; i < 3; i++)
108  {
109  //
110  // Send transfer payload encapsulated in a ECom protocol frame
111  //
112  errorCode = sbgEComProtocolSend(&pHandle->protocolHandle, msgClass, msg, sbgStreamBufferGetLinkedBuffer(&streamBuffer), sbgStreamBufferGetLength(&streamBuffer));
113 
114  if (errorCode == SBG_NO_ERROR)
115  {
116  //
117  // If the device receives the frame successfully received, it responds with an ACK, wait for the answer
118  //
119  errorCode = sbgEComWaitForAck(pHandle, msgClass, msg, pHandle->cmdDefaultTimeOut);
120 
121  //
122  // Test if the response is positive from device
123  //
124  if (errorCode == SBG_NO_ERROR)
125  {
126  //
127  // Ack received, no need for other trial
128  //
129  break;
130  }
131  }
132  }
133 
134  return errorCode;
135 }
136 
144 static SbgErrorCode sbgEComTransferSendEnd(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg)
145 {
146  SbgErrorCode errorCode = SBG_NO_ERROR;
147  SbgStreamBuffer outStreamBuffer;
148  uint8_t outputBuffer[sizeof(uint16_t)];
149  uint32_t i;
150 
151  assert(pHandle);
152 
153  //
154  // Initialize stream buffer for output
155  //
156  sbgStreamBufferInitForWrite(&outStreamBuffer, outputBuffer, sizeof(outStreamBuffer));
157 
158  //
159  // Build payload, only a SBG_ECOM_TRANSFER_END cmd
160  //
162 
163  //
164  // Send command (multiple times in case of failures)
165  //
166  for (i = 0; i < 3; i++)
167  {
168  //
169  // Send upload end payload encapsulated in a ECom protocol frame
170  //
171  errorCode = sbgEComProtocolSend(&pHandle->protocolHandle, msgClass, msg, sbgStreamBufferGetLinkedBuffer(&outStreamBuffer), sbgStreamBufferGetLength(&outStreamBuffer));
172 
173  if (errorCode == SBG_NO_ERROR)
174  {
175  //
176  // If the device finishes the sequence successfully, it responds with an ACK, wait for answer
177  //
178  errorCode = sbgEComWaitForAck(pHandle, msgClass, msg, pHandle->cmdDefaultTimeOut);
179 
180  //
181  // Test if the response is positive from device
182  //
183  if (errorCode == SBG_NO_ERROR)
184  {
185  //
186  // ACK received, no need for other trial
187  //
188  break;
189  }
190  }
191  }
192 
193  return errorCode;
194 }
195 
204 static SbgErrorCode sbgEComTransferReceiveInit(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, size_t *pSize)
205 {
206  SbgErrorCode errorCode = SBG_NO_ERROR;
207  SbgStreamBuffer outStreamBuffer;
208  SbgStreamBuffer inStreamBuffer;
209  uint8_t inputBuffer[SBG_ECOM_MAX_PAYLOAD_SIZE];
210  uint8_t outputBuffer[sizeof(uint16_t)];
211  uint8_t receivedMsgClass;
212  uint8_t receivedMsg;
213  uint16_t transferCmd;
214  size_t inputSize;
215  size_t transferSize;
216  uint32_t i;
217 
218  assert(pHandle);
219 
220  //
221  // Initialize stream buffer for output
222  //
223  sbgStreamBufferInitForWrite(&outStreamBuffer, outputBuffer, sizeof(outStreamBuffer));
224 
225  //
226  // Build payload, only a SBG_ECOM_TRANSFER_START cmd
227  //
229 
230  //
231  // Send command (multiple times in case of failures)
232  //
233  for (i = 0; i < 3; i++)
234  {
235  //
236  // Send transfer payload encapsulated in an ECom protocol frame
237  //
238  errorCode = sbgEComProtocolSend(&pHandle->protocolHandle, msgClass, msg, sbgStreamBufferGetLinkedBuffer(&outStreamBuffer), sbgStreamBufferGetLength(&outStreamBuffer));
239 
240  if (errorCode == SBG_NO_ERROR)
241  {
242  //
243  // Wait for reponse, the device should respond with a ECOM_TRANSFER_START command and the transfer size
244  // If it can not initiate the transfer, it will respond with a NACK
245  //
246  errorCode = sbgEComReceiveAnyCmd(pHandle, &receivedMsgClass, &receivedMsg, inputBuffer, &inputSize, SBG_ECOM_MAX_PAYLOAD_SIZE, pHandle->cmdDefaultTimeOut);
247 
248  if (errorCode == SBG_NO_ERROR)
249  {
250  //
251  // Test if the command received is the one expected
252  //
253  if ((receivedMsgClass == msgClass) && (receivedMsg == msg))
254  {
255  //
256  // Init stream buffer on received payload to process it
257  //
258  sbgStreamBufferInitForRead(&inStreamBuffer, inputBuffer, inputSize);
259 
260  //
261  // Retrieve parameters, the first one is the transfer command
262  // The second one is the total transfer size
263  //
264  transferCmd = sbgStreamBufferReadUint16LE(&inStreamBuffer);
265  transferSize = sbgStreamBufferReadSizeT32LE(&inStreamBuffer);
266 
267  //
268  // The device should have answered with SBG_ECOM_TRANSFER_START transfer command
269  //
270  if (transferCmd == SBG_ECOM_TRANSFER_START)
271  {
272  //
273  // Update output variable with the transfer size
274  //
275  *pSize = transferSize;
276 
277  //
278  // No need for other trials, exit loop/
279  //
280  break;
281  }
282  else
283  {
284  //
285  // Invalid transfer command response
286  //
287  errorCode = SBG_ERROR;
288  }
289  }
290  else
291  {
292  //
293  // This is not the command expected
294  //
295  errorCode = SBG_ERROR;
296  }
297  }
298  }
299  }
300 
301  return errorCode;
302 }
303 
314 static SbgErrorCode sbgEComTransferReceiveData(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, void *pBuffer, size_t offset, size_t packetSize)
315 {
316  SbgErrorCode errorCode = SBG_NO_ERROR;
317  SbgStreamBuffer outStreamBuffer;
318  SbgStreamBuffer inStreamBuffer;
319  uint8_t outputBuffer[SBG_ECOM_MAX_PAYLOAD_SIZE];
320  uint8_t inputBuffer[SBG_ECOM_MAX_PAYLOAD_SIZE];
321  uint16_t transferCmd;
322  uint8_t receivedMsgClass;
323  uint8_t receivedMsg;
324  size_t rcvdOffset;
325  size_t inputSize;
326  uint32_t i;
327 
328  assert(pHandle);
329  assert(pBuffer);
330  assert(packetSize > 0);
331 
332  //
333  // Initialize stream buffer for output
334  //
335  sbgStreamBufferInitForWrite(&outStreamBuffer, outputBuffer, sizeof(outputBuffer));
336 
337  //
338  // Build payload: an SBG_ECOM_TRANSFER_DATA transfer command, the offset from the start of the transfer, the size of the packet the device must send
339  //
341  sbgStreamBufferWriteSizeT32LE(&outStreamBuffer, offset);
342  sbgStreamBufferWriteSizeT32LE(&outStreamBuffer, packetSize);
343 
344  //
345  // Send command (multiple times in case of failures)
346  //
347  for (i = 0; i < 3; i++)
348  {
349  //
350  // Send transfer payload encapsulated in an ECom protocol frame
351  //
352  errorCode = sbgEComProtocolSend(&pHandle->protocolHandle, msgClass, msg, sbgStreamBufferGetLinkedBuffer(&outStreamBuffer), sbgStreamBufferGetLength(&outStreamBuffer));
353 
354  if (errorCode == SBG_NO_ERROR)
355  {
356  //
357  // Wait for reponse, the device should respond with a ECOM_TRANSFER_DATA, the offset from the start of the transfer and the data payload
358  // If it can not provide the data, it will respond with a NACK
359  //
360  errorCode = sbgEComReceiveAnyCmd(pHandle, &receivedMsgClass, &receivedMsg, inputBuffer, &inputSize, SBG_ECOM_MAX_PAYLOAD_SIZE, pHandle->cmdDefaultTimeOut);
361 
362  if (errorCode == SBG_NO_ERROR)
363  {
364  //
365  // Test if this is the protocol command expected
366  //
367  if ((receivedMsgClass == msgClass) && (receivedMsg == msg))
368  {
369  //
370  // Initialize stream buffer for read on input buffer
371  //
372  sbgStreamBufferInitForRead(&inStreamBuffer, inputBuffer, inputSize);
373 
374  //
375  // Read response fields, first is the transfer command, second is the offset
376  //
377  transferCmd = sbgStreamBufferReadUint16LE(&inStreamBuffer);
378  rcvdOffset = sbgStreamBufferReadSizeT32LE(&inStreamBuffer);
379 
380  //
381  // Test that it's a SBG_ECOM_TRANSFER_DATA command
382  // The data is at the offset asked
383  // And the size corresponds
384  //
385  if ( (transferCmd == SBG_ECOM_TRANSFER_DATA) && (offset == rcvdOffset) && (packetSize == (inputSize - (sizeof(uint16_t) + sizeof(uint32_t)))) )
386  {
387  //
388  // Read then all the buffer
389  //
390  sbgStreamBufferReadBuffer(&inStreamBuffer, pBuffer, inputSize - (sizeof(uint16_t) + sizeof(uint32_t)));
391 
392  //
393  // No need for other trials, exit loop
394  //
395  break;
396  }
397  }
398  else
399  {
400  //
401  // Not the command expected
402  //
403  errorCode = SBG_ERROR;
404  }
405  }
406  }
407  }
408 
409  return errorCode;
410 }
411 
419 static SbgErrorCode sbgEComTransferReceiveEnd(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg)
420 {
421  SbgErrorCode errorCode = SBG_NO_ERROR;
422  SbgStreamBuffer outStreamBuffer;
423  uint8_t outputBuffer[sizeof(uint16_t)];
424  uint32_t i;
425 
426  assert(pHandle);
427 
428  //
429  // Initialize stream buffer for output
430  //
431  sbgStreamBufferInitForWrite(&outStreamBuffer, outputBuffer, sizeof(outStreamBuffer));
432 
433  //
434  // Build payload, only a SBG_ECOM_TRANSFER_END cmd
435  //
437 
438  //
439  // Send command (multiple times in case of failures)
440  //
441  for (i = 0; i < 3; i++)
442  {
443  //
444  // Send upload end payload encapsulated in a ECom protocol frame
445  //
446  errorCode = sbgEComProtocolSend(&pHandle->protocolHandle, msgClass, msg, sbgStreamBufferGetLinkedBuffer(&outStreamBuffer), sbgStreamBufferGetLength(&outStreamBuffer));
447 
448  if (errorCode == SBG_NO_ERROR)
449  {
450  //
451  // If the device is able to finish transfer sequence, it responds with an ACK
452  //
453  errorCode = sbgEComWaitForAck(pHandle, msgClass, msg, pHandle->cmdDefaultTimeOut);
454 
455  //
456  // Test if the response is positive from device
457  //
458  if (errorCode == SBG_NO_ERROR)
459  {
460  //
461  // No need for other trial, exit loop
462  //
463  break;
464  }
465  }
466  }
467 
468  return errorCode;
469 }
470 
471 //----------------------------------------------------------------------//
472 //- Public transfer method definitions -//
473 //----------------------------------------------------------------------//
474 
484 SbgErrorCode sbgEComTransferSend(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, const void *pBuffer, size_t size)
485 {
486  SbgErrorCode errorCode = SBG_NO_ERROR;
487  SbgSplitBuffer splitBuffer;
488  size_t i;
489 
490  assert(pHandle);
491  assert(pBuffer);
492  assert(size > 0);
493 
494  //
495  // Make sure we are not trying to send a buffer that is too large
496  //
497  if (size <= SBG_ECOM_TRANSFER_MAX_SIZE)
498  {
499  //
500  // Initiate data transfer
501  //
502  errorCode = sbgEComTransferSendInit(pHandle, msgClass, msg, size);
503 
504  //
505  // Check that the transfer was correctly initialized
506  //
507  if (errorCode == SBG_NO_ERROR)
508  {
509  //
510  // Initialize split buffer that will help with splitting up provided buffer
511  //
512  sbgSplitBufferInitForRead(&splitBuffer, pBuffer, size, SBG_ECOM_TRANSFER_PACKET_SIZE);
513 
514  //
515  // Transfer sub buffer one by one
516  //
517  for (i = 0; i < sbgSplitBufferGetSubBufferNbr(&splitBuffer); i++)
518  {
519  //
520  // Send a sub buffer
521  //
522  errorCode = sbgEComTransferSendData(pHandle, msgClass, msg, sbgSplitBufferGetSubBuffer(&splitBuffer, i), sbgSplitBufferGetSubBufferOffset(&splitBuffer, i), sbgSplitBufferGetSubBufferSize(&splitBuffer, i));
523 
524  //
525  // Test if the sub buffer has been sent
526  //
527  if (errorCode != SBG_NO_ERROR)
528  {
529  //
530  // Unable to send a sub buffer, abort send operation.
531  //
532  break;
533  }
534  }
535 
536  //
537  // Test if any error occurred during data transfer
538  //
539  if (errorCode == SBG_NO_ERROR)
540  {
541  //
542  // End data transfer
543  //
544  errorCode = sbgEComTransferSendEnd(pHandle, msgClass, msg);
545  }
546  }
547  }
548  else
549  {
550  //
551  // Trying to send a buffer that is too large
552  //
553  errorCode = SBG_INVALID_PARAMETER;
554  }
555 
556  return errorCode;
557 }
558 
569 SbgErrorCode sbgEComTransferReceive(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, void *pBuffer, size_t *pActualSize, size_t bufferSize)
570 {
571  SbgErrorCode errorCode = SBG_NO_ERROR;
572  SbgSplitBuffer splitBuffer;
573  size_t transferSize;
574  size_t i;
575 
576  assert(pHandle);
577  assert(pBuffer);
578  assert(pActualSize);
579  assert(bufferSize > 0);
580 
581  //
582  // initiate data transfer
583  //
584  errorCode = sbgEComTransferReceiveInit(pHandle, msgClass, msg, &transferSize);
585 
586  //
587  // Make sure the receive transfer has been correctly initialized
588  //
589  if (errorCode == SBG_NO_ERROR)
590  {
591  //
592  // Test that the provided buffer is large enough to receive all data
593  //
594  if (transferSize <= bufferSize)
595  {
596  //
597  // Initialize Split buffer to help with sub buffer receive
598  //
599  sbgSplitBufferInitForWrite(&splitBuffer, pBuffer, transferSize, SBG_ECOM_TRANSFER_PACKET_SIZE);
600 
601  //
602  // Receive buffers one by one
603  //
604  for (i = 0; i < sbgSplitBufferGetSubBufferNbr(&splitBuffer); i++)
605  {
606  //
607  // Receive a sub buffer
608  //
609  errorCode = sbgEComTransferReceiveData(pHandle, msgClass, msg, sbgSplitBufferGetSubBuffer(&splitBuffer, i), sbgSplitBufferGetSubBufferOffset(&splitBuffer, i), sbgSplitBufferGetSubBufferSize(&splitBuffer, i));
610 
611  //
612  // Make sure that the sub buffer has been correctly received
613  //
614  if (errorCode != SBG_NO_ERROR)
615  {
616  //
617  // An error occurred, abort data transfer
618  //
619  break;
620  }
621  }
622 
623  //
624  // Test if any error occurred during transfer
625  //
626  if (errorCode == SBG_NO_ERROR)
627  {
628  //
629  // End data transfer
630  //
631  errorCode = sbgEComTransferReceiveEnd(pHandle, msgClass, msg);
632 
633  //
634  // Make sure that the transfer has been correctly ended
635  //
636  if (errorCode == SBG_NO_ERROR)
637  {
638  //
639  // Since the transfer was successful update output variable pActualSize
640  //
641  *pActualSize = transferSize;
642  }
643  }
644  }
645  else
646  {
647  //
648  // Provided buffer is too small
649  //
650  errorCode = SBG_INVALID_PARAMETER;
651  }
652  }
653 
654  return errorCode;
655 }
SBG_INLINE size_t sbgSplitBufferGetSubBufferNbr(const SbgSplitBuffer *pSplitBuffer)
static SbgErrorCode sbgEComTransferReceiveEnd(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg)
SBG_INLINE SbgErrorCode sbgStreamBufferInitForRead(SbgStreamBuffer *pHandle, const void *pLinkedBuffer, size_t bufferSize)
SBG_INLINE size_t sbgStreamBufferReadSizeT32LE(SbgStreamBuffer *pHandle)
Helper methods used to handle a splittable buffer.
static SbgErrorCode sbgEComTransferSendData(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, const void *pBuffer, size_t offset, size_t packetSize)
Used to read/write data from/to a memory buffer stream.
SBG_INLINE SbgErrorCode sbgStreamBufferWriteSizeT32LE(SbgStreamBuffer *pHandle, size_t value)
SbgErrorCode sbgEComProtocolSend(SbgEComProtocol *pHandle, uint8_t msgClass, uint8_t msg, const void *pData, size_t size)
static SbgErrorCode sbgEComTransferReceiveInit(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, size_t *pSize)
SBG_INLINE size_t sbgSplitBufferGetSubBufferOffset(const SbgSplitBuffer *pSplitBuffer, size_t subBufferIdx)
static SbgErrorCode sbgEComTransferSendEnd(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg)
Handle large send/receive transfer for specific ECom Protocol commands.
#define SBG_ECOM_TRANSFER_MAX_SIZE
SbgEComProtocol protocolHandle
Definition: sbgECom.h:72
SBG_INLINE SbgErrorCode sbgStreamBufferInitForWrite(SbgStreamBuffer *pHandle, void *pLinkedBuffer, size_t bufferSize)
SBG_INLINE uint16_t sbgStreamBufferReadUint16LE(SbgStreamBuffer *pHandle)
SbgErrorCode sbgEComTransferSend(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, const void *pBuffer, size_t size)
#define SBG_ECOM_TRANSFER_PACKET_SIZE
SbgErrorCode sbgEComWaitForAck(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, uint32_t timeOut)
SBG_INLINE SbgErrorCode sbgStreamBufferReadBuffer(SbgStreamBuffer *pHandle, void *pBuffer, size_t numBytesToRead)
uint32_t cmdDefaultTimeOut
Definition: sbgECom.h:78
SBG_INLINE void * sbgStreamBufferGetLinkedBuffer(SbgStreamBuffer *pHandle)
SBG_INLINE size_t sbgSplitBufferGetSubBufferSize(const SbgSplitBuffer *pSplitBuffer, size_t subBufferIdx)
SBG_INLINE void * sbgSplitBufferGetSubBuffer(const SbgSplitBuffer *pSplitBuffer, size_t subBufferIdx)
SBG_INLINE SbgErrorCode sbgStreamBufferWriteBuffer(SbgStreamBuffer *pHandle, const void *pBuffer, size_t numBytesToWrite)
static SbgErrorCode sbgEComTransferSendInit(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, size_t size)
SBG_INLINE void sbgSplitBufferInitForWrite(SbgSplitBuffer *pSplitBuffer, void *pBuffer, size_t bufferSize, size_t subBufferSize)
SbgErrorCode sbgEComTransferReceive(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, void *pBuffer, size_t *pActualSize, size_t bufferSize)
SbgErrorCode sbgEComReceiveAnyCmd(SbgEComHandle *pHandle, uint8_t *pMsgClass, uint8_t *pMsg, void *pData, size_t *pSize, size_t maxSize, uint32_t timeOut)
SBG_INLINE void sbgSplitBufferInitForRead(SbgSplitBuffer *pSplitBuffer, const void *pBuffer, size_t bufferSize, size_t subBufferSize)
SBG_INLINE size_t sbgStreamBufferGetLength(SbgStreamBuffer *pHandle)
SBG_INLINE SbgErrorCode sbgStreamBufferWriteUint16LE(SbgStreamBuffer *pHandle, uint16_t value)
#define SBG_ECOM_MAX_PAYLOAD_SIZE
enum _SbgErrorCode SbgErrorCode
static SbgErrorCode sbgEComTransferReceiveData(SbgEComHandle *pHandle, uint8_t msgClass, uint8_t msg, void *pBuffer, size_t offset, size_t packetSize)


sbg_driver
Author(s): SBG Systems
autogenerated on Thu Oct 22 2020 03:47:22