summaryrefslogtreecommitdiff
path: root/lcmodule/source/cnh1605205_ldr_network_layer/source/a2_network.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcmodule/source/cnh1605205_ldr_network_layer/source/a2_network.c')
-rw-r--r--lcmodule/source/cnh1605205_ldr_network_layer/source/a2_network.c599
1 files changed, 599 insertions, 0 deletions
diff --git a/lcmodule/source/cnh1605205_ldr_network_layer/source/a2_network.c b/lcmodule/source/cnh1605205_ldr_network_layer/source/a2_network.c
new file mode 100644
index 0000000..19d7800
--- /dev/null
+++ b/lcmodule/source/cnh1605205_ldr_network_layer/source/a2_network.c
@@ -0,0 +1,599 @@
+/*******************************************************************************
+ * Copyright (C) ST-Ericsson SA 2011
+ * License terms: 3-clause BSD license
+ ******************************************************************************/
+/**
+ * @addtogroup ldr_communication_serv
+ * @{
+ * @addtogroup a2_family
+ * @{
+ * @addtogroup ldr_network_layer
+ * @{
+ */
+
+/*******************************************************************************
+ * Includes
+ ******************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "c_system.h"
+#include "r_basicdefinitions.h"
+#include "r_a2_family.h"
+#include "r_a2_transport.h"
+#include "r_a2_network.h"
+#include "r_a2_protocol.h"
+#include "r_a2_header.h"
+#include "r_communication_service.h"
+#include "r_debug.h"
+#include "r_debug_macro.h"
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+/*******************************************************************************
+ * Declaration of file local functions
+ ******************************************************************************/
+static ErrorCode_e A2_Network_ReceiveHeader(const Communication_t *const Communication_p);
+static ErrorCode_e A2_Network_ReceivePayload(Communication_t *Communication_p);
+static ErrorCode_e A2_Network_RegisterRetransmission(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p);
+static void A2_Network_RetransmissionCallback(Communication_t *Communication_p, const void *const Timer_p, void *Data_p);
+static void A2_InHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p);
+#ifdef CFG_ENABLE_LOADER_TYPE
+static void A2_QueueCallback(const void *const Queue_p, void *Param_p);
+#endif //CFG_ENABLE_LOADER_TYPE
+
+/*******************************************************************************
+ * File scope types, constants and variables
+ ******************************************************************************/
+#define A2_RESET_INBOUND(c, s) do { (c)->ReqData = 0; (c)->RecData = 0; (c)->ReqBuffOffset = 0; (c)->Target_p = NULL; (c)->State = (s); } while(0);
+#define A2_SYNC_HEADER(c, d, t) do { (c)->ReqData = d; (c)->Target_p = t; } while(0);
+#define A2_SET_INBOUND(c, s, d) do { (c)->ReqData = d; (c)->RecData = 0; (c)->ReqBuffOffset = 0; (c)->State = (s); } while(0);
+
+/*******************************************************************************
+ * Definition of external functions
+ ******************************************************************************/
+
+/*
+ * Initializes the A2 network layer.
+ *
+ * @param [in,out] Communication_p Communication module context.
+ *
+ * @retval E_SUCCESS After successful execution.
+ * @retval E_FAILED_TO_INIT_COM_DEVICE Fail to initialize the communication
+ * device.
+ */
+ErrorCode_e A2_Network_Initialize(Communication_t *Communication_p)
+{
+ memset(A2_NETWORK(Communication_p), 0, sizeof(A2_NetworkContext_t));
+
+ /* Simulate a finished read to get the inbound state-machine going. */
+ A2_Network_ReadCallback(NULL, 0, Communication_p);
+ A2_NETWORK(Communication_p)->Outbound.InLoad = FALSE;
+
+#ifdef CFG_ENABLE_LOADER_TYPE
+ (void)QUEUE(Communication_p, Fifo_SetCallback_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p, QUEUE_NONEMPTY, A2_QueueCallback, Communication_p);
+#endif
+ A2_NETWORK(Communication_p)->Inbound.LCM_Error = E_SUCCESS;
+ A2_NETWORK(Communication_p)->Outbound.LCM_Error = E_SUCCESS;
+
+ return E_SUCCESS;
+}
+
+/*
+ * Shut down the A2 network layer.
+ *
+ * @param [in,out] Communication_p Communication module context.
+ *
+ * @retval E_SUCCESS After successful execution.
+ */
+ErrorCode_e A2_Network_Shutdown(const Communication_t *const Communication_p)
+{
+ ErrorCode_e ReturnValue = E_SUCCESS;
+
+ (void)QUEUE(Communication_p, Fifo_SetCallback_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p, QUEUE_NONEMPTY, NULL, NULL);
+ (void)QUEUE(Communication_p, Fifo_SetCallback_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p, QUEUE_EMPTY, NULL, NULL);
+
+
+ /* Wait until the all packets in the queue has released. */
+ while (!QUEUE(Communication_p, Fifo_IsEmpty_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p)) {
+ A2_PacketMeta_t *Packet_p = (A2_PacketMeta_t *)QUEUE(Communication_p, FifoDequeue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p);
+
+ if (Packet_p->Header.Protocol != A2_PROTOCOL) {
+ ReturnValue = A2_Network_PacketRelease(Communication_p, Packet_p);
+ VERIFY(E_SUCCESS == ReturnValue, ReturnValue);
+ }
+ }
+
+ (void)QUEUE(Communication_p, Fifo_SetCallback_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p, QUEUE_NONEMPTY, NULL, NULL);
+ (void)QUEUE(Communication_p, Fifo_SetCallback_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p, QUEUE_EMPTY, NULL, NULL);
+
+ /* Wait until the all packets in the queue has released. */
+ while (!QUEUE(Communication_p, Fifo_IsEmpty_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p)) {
+ ReturnValue = A2_Network_PacketRelease(Communication_p, (A2_PacketMeta_t *)QUEUE(Communication_p, FifoDequeue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p));
+ }
+
+ErrorExit:
+ return ReturnValue;
+}
+
+
+/*
+ * Handler for received packets in A2 protocl family.
+ *
+ * This callback function handles the received packets.
+ *
+ * @param [in] Data_p Pointer to the received data.
+ * @param [in] Length Length of the received data.
+ * @param [in] Param_p Parameters;
+ *
+ * @return none.
+ */
+void A2_Network_ReadCallback(const void *Data_p, const uint32 Length, void *Param_p)
+{
+ IDENTIFIER_NOT_USED(Data_p);
+ Communication_t *Communication_p = (Communication_t *)Param_p;
+
+ C_(printf("a2_network.c (%d) RecLength(%d) RecBackupData (%d)\n", __LINE__, Length, A2_NETWORK(Communication_p)->Inbound.RecBackupData);)
+ A2_NETWORK(Communication_p)->Inbound.RecData += Length + A2_NETWORK(Communication_p)->Inbound.RecBackupData;
+ A2_NETWORK(Communication_p)->Inbound.RecBackupData = 0;
+
+ if (A2_NETWORK(Communication_p)->Inbound.ReqData == 0) {
+ ErrorCode_e ReturnValue = E_GENERAL_COMMUNICATION_ERROR;
+
+ switch (A2_NETWORK(Communication_p)->Inbound.State) {
+ case A2_RECEIVE_HEADER:
+ ReturnValue = A2_Network_ReceiveHeader(Communication_p);
+ break;
+ case A2_RECEIVE_PAYLOAD:
+ ReturnValue = A2_Network_ReceivePayload(Communication_p);
+ break;
+ default:
+ A2_NETWORK(Communication_p)->Inbound.State = A2_RECEIVE_HEADER;
+ A2_NETWORK(Communication_p)->Inbound.RecData = 0;
+ A2_NETWORK(Communication_p)->Inbound.ReqData = A2_HEADER_LENGTH;
+ A2_NETWORK(Communication_p)->Inbound.Target_p = A2_NETWORK(Communication_p)->Inbound.Scratch;
+ A2_NETWORK(Communication_p)->Inbound.LCM_Error = E_SUCCESS;
+ ReturnValue = E_SUCCESS;
+ break;
+ }
+
+#ifdef CFG_ENABLE_LOADER_TYPE
+ ReturnValue = A2_Network_ReceiverHandler(Communication_p);
+#endif
+
+ if (E_SUCCESS != ReturnValue) {
+ A2_NETWORK(Communication_p)->Inbound.State = A2_RECEIVE_ERROR;
+ }
+
+ A2_NETWORK(Communication_p)->Inbound.LCM_Error = ReturnValue;
+ }
+}
+
+/*
+ * Handler for receiving new data.
+ *
+ * This function checks if new data has been received.
+ *
+ * @param [in,out] Communication_p Communication module context.
+ *
+ * @return none.
+ */
+ErrorCode_e A2_Network_ReceiverHandler(Communication_t *Communication_p)
+{
+ uint32 ReqData;
+ A2_Inbound_t *In_p = &(A2_NETWORK(Communication_p)->Inbound);
+
+ if (In_p->ReqData > 0) {
+ if (Communication_p->BackupCommBufferSize != 0) {
+ if (Communication_p->BackupCommBufferSize < In_p->ReqData) {
+ memcpy(In_p->Target_p + In_p->ReqBuffOffset, Communication_p->BackupCommBuffer_p, Communication_p->BackupCommBufferSize);
+ In_p->RecBackupData = Communication_p->BackupCommBufferSize;
+ (void)Communication_p->CommunicationDevice_p->Read(In_p->Target_p + In_p->ReqBuffOffset + Communication_p->BackupCommBufferSize,
+ In_p->ReqData - Communication_p->BackupCommBufferSize,
+ A2_Network_ReadCallback, Communication_p);
+ C_(printf("a2_network.c (%d) ReqData(%d) RecData(%d)\n", __LINE__, In_p->ReqData, In_p->RecData);)
+ C_(printf("a2_network.c (%d) Communication_p->BackupCommBufferSize(%d) RecBackupData (%d)\n", __LINE__, Communication_p->BackupCommBufferSize, In_p->RecBackupData);)
+ In_p->RecData = 0;
+ In_p->ReqBuffOffset = 0;
+ Communication_p->BackupCommBufferSize = 0;
+ In_p->ReqData = 0;
+ } else {
+ memcpy(In_p->Target_p + In_p->ReqBuffOffset, Communication_p->BackupCommBuffer_p, In_p->ReqData);
+ Communication_p->BackupCommBufferSize = Communication_p->BackupCommBufferSize - In_p->ReqData;
+ ReqData = In_p->ReqData;
+ In_p->ReqData = 0;
+ A2_Network_ReadCallback(In_p->Target_p + In_p->ReqBuffOffset, ReqData, Communication_p);
+ In_p->RecData = 0;
+ }
+ } else {
+ ReqData = In_p->ReqData;
+ In_p->ReqData = 0;
+ (void)Communication_p->CommunicationDevice_p->Read(In_p->Target_p + In_p->ReqBuffOffset, ReqData, A2_Network_ReadCallback, Communication_p);
+ C_(printf("a2_network.c (%d) ReqData(%d) RecData(%d) \n", __LINE__, In_p->ReqData, In_p->RecData);)
+ C_(printf("a2_network.c (%d) Communication_p->BackupCommBufferSize(%d) RecBackupData (%d)\n", __LINE__, Communication_p->BackupCommBufferSize, In_p->RecBackupData);)
+ In_p->RecData = 0;
+ In_p->ReqBuffOffset = 0;
+ }
+ }
+
+ /* check for receiver sinhronization */
+ if (In_p->State == A2_RECEIVE_ERROR) {
+ A2_RESET_INBOUND(In_p, A2_RECEIVE_HEADER);
+ A2_SYNC_HEADER(In_p, A2_HEADER_LENGTH, In_p->Scratch);
+ //(void)Communication_p->CommunicationDevice_p->Read(In_p->Target_p, A2_HEADER_LENGTH, A2_Network_ReadCallback, Communication_p);
+ }
+
+ return A2_NETWORK(Communication_p)->Inbound.LCM_Error;
+}
+
+/*
+ * Cancel retransmission of packets.
+ *
+ * @param [in,out] Communication_p Communication module context.
+ * @param [in] UniqueKey Unique key used for identification of packet
+ * for retransmission.
+ *
+ * @return none.
+ */
+ErrorCode_e A2_Network_CancelRetransmission(const Communication_t *const Communication_p, uint32 UniqueKey)
+{
+ ErrorCode_e ReturnValue = E_SUCCESS;
+ uint32 SequenceNumber = A2_NETWORK(Communication_p)->Outbound.Packet_p->Header.SequenceNumber;
+
+ if (SequenceNumber != UniqueKey) {
+ A_(printf("a2_network.c(%d): Cancel packet retransmission error: SequenceNumber = %u, UniqueKey = %u\n", __LINE__, SequenceNumber, UniqueKey);)
+ return E_GENERAL_FATAL_ERROR;
+ }
+
+ (void)TIMER(Communication_p, TimerRelease_Fn)(OBJECT_TIMER(Communication_p), A2_NETWORK(Communication_p)->RetransmissionContext.TimerKey);
+ free(A2_NETWORK(Communication_p)->Outbound.Packet_p->Timer_p);
+ ReturnValue = A2_Network_PacketRelease(Communication_p, A2_NETWORK(Communication_p)->Outbound.Packet_p);
+
+ if (E_SUCCESS != ReturnValue) {
+ A_(printf("a2_network.c(%d): Packet release failed\n", __LINE__);)
+ return ReturnValue;
+ }
+
+ A2_NETWORK(Communication_p)->Outbound.State = A2_SEND_IDLE;
+ A2_NETWORK(Communication_p)->Outbound.Packet_p = NULL;
+
+ return ReturnValue;
+}
+
+/*
+ * Network packet allocation in A2 protocol family.
+ *
+ * @param [in,out] Communication_p Communication module context.
+ * @param [in] BufferSize Size of buffer used for network packet.
+ *
+ * @retval Pointer Pointer to allocated packet meta info.
+ * @retval NULL if allocation fail.
+ */
+A2_PacketMeta_t *A2_Network_PacketAllocate(const Communication_t *const Communication_p, int BufferSize)
+{
+ A2_PacketMeta_t *Meta_p = NULL;
+ void *Buffer_p = NULL;
+ int BuffersNr = 0;
+
+ /* Find the first unallocated buffers. */
+ Buffer_p = BUFFER(Communication_p, BufferAllocate_Fn)(OBJECT_BUFFER(Communication_p), BufferSize);
+
+ if (NULL == Buffer_p) {
+ A_(printf("a2_network.c (%d): ** Buffer allocation fail! **\n", __LINE__);)
+ goto ErrorExit;
+ }
+
+ B_(printf("a2_network.c (%d): Buffer allocate (0x%x)! **\n", __LINE__, (uint32)Buffer_p);)
+
+ /* packet meta info allocate */
+ Meta_p = (A2_PacketMeta_t *)malloc(sizeof(A2_PacketMeta_t));
+
+ if (NULL == Meta_p) {
+ A2_NETWORK(Communication_p)->Inbound.LCM_Error = E_ALLOCATE_FAILED;
+ goto ErrorExit;
+ }
+
+ /* packet meta info setup */
+ Meta_p->Buffer_p = (uint8 *)Buffer_p;
+ Meta_p->BufferSize = BufferSize;
+ Meta_p->Flags = A2_BUF_ALLOCATED;
+
+ do {
+ if (NULL == A2_NETWORK(Communication_p)->MetaInfoList[BuffersNr]) {
+ A2_NETWORK(Communication_p)->MetaInfoList[BuffersNr] = Meta_p;
+ break;
+ }
+
+ BuffersNr++;
+ } while (BuffersNr < (A2_COMMAND_BUFFER_COUNT));
+
+ErrorExit:
+ return Meta_p;
+}
+
+/*
+ * Network packet release in A2 protocol family.
+ *
+ * @param [in,out] Communication_p Communication module context.
+ * @param [in] Meta_p Meta info for used network packet.
+ *
+ * @retval E_SUCCESS Successful network packet release.
+ * @retval E_INVALID_INPUT_PARAMETERS Invalid input parameter.
+ */
+ErrorCode_e A2_Network_PacketRelease(const Communication_t *const Communication_p, A2_PacketMeta_t *Meta_p)
+{
+ ErrorCode_e ReturnValue = E_SUCCESS;
+ int BuffersNr = 0;
+
+ VERIFY(NULL != Meta_p, E_INVALID_INPUT_PARAMETERS);
+
+ /* remove the meta info data from list */
+ do {
+ if (Meta_p == A2_NETWORK(Communication_p)->MetaInfoList[BuffersNr]) {
+ /* release buffer */
+ B_(printf("a2_network.c (%d): Buffer release (0x%x)! **\n", __LINE__, (uint32)(Meta_p->Buffer_p));)
+ ReturnValue = BUFFER(Communication_p, BufferRelease_Fn)(OBJECT_BUFFER(Communication_p), Meta_p->Buffer_p, Meta_p->BufferSize);
+ VERIFY(E_SUCCESS == ReturnValue, ReturnValue);
+ B_(printf("a2_network.c (%d): Buffer released! **\n", __LINE__);)
+
+ A2_NETWORK(Communication_p)->MetaInfoList[BuffersNr] = NULL;
+ memset(Meta_p, 0, sizeof(A2_PacketMeta_t));
+ break;
+ }
+
+ BuffersNr++;
+ } while (BuffersNr < (A2_COMMAND_BUFFER_COUNT));
+
+ErrorExit:
+ return ReturnValue;
+}
+
+/*
+ * Handler function that is called after successful transmission of a packet.
+ *
+ * If new packet is ready for transmitting it starts
+ * the transmission of the packet.
+ *
+ * @param [in] Data_p Pointer to the data for transmitting.
+ * @param [in] Length Length of the received data.
+ * @param [in] Param_p Parameters.
+ *
+ * @return none.
+ */
+void A2_Network_WriteCallback(const void *Data_p, const uint32 Length, void *Param_p)
+{
+ IDENTIFIER_NOT_USED(Data_p);
+ IDENTIFIER_NOT_USED(Length);
+ Communication_t *Communication_p = (Communication_t *)Param_p;
+ A2_Outbound_t *Out_p = &(A2_NETWORK(Communication_p)->Outbound);
+
+ if (A2_SENDING_PAYLOAD == Out_p->State) {
+ if (NULL != Out_p->Packet_p->Timer_p) {
+ (void)A2_Network_RegisterRetransmission(Communication_p, Out_p->Packet_p);
+ } else {
+ (void)A2_Network_PacketRelease(Communication_p, Out_p->Packet_p);
+ Out_p->State = A2_SEND_IDLE;
+ Out_p->Packet_p = NULL;
+ }
+ } else if (A2_SENDING_HEADER == Out_p->State) {
+ Out_p->State = A2_SEND_PAYLOAD;
+ } else {
+ /* should never happen
+ TODO: Error handling */
+ }
+
+#ifdef CFG_ENABLE_LOADER_TYPE
+
+ if (E_SUCCESS != A2_Network_TransmiterHandler(Communication_p)) {
+ A2_NETWORK(Communication_p)->Outbound.LCM_Error = E_GENERAL_COMMUNICATION_ERROR;
+ }
+
+#endif
+}
+
+
+/*******************************************************************************
+ * Definition of internal functions
+ ******************************************************************************/
+static ErrorCode_e A2_Network_ReceiveHeader(const Communication_t *const Communication_p)
+{
+ A2_Inbound_t *In_p = &(A2_NETWORK(Communication_p)->Inbound);
+ ErrorCode_e ReturnValue = E_SUCCESS;
+
+ if (In_p->RecData == 0) {
+ In_p->ReqData = A2_HEADER_LENGTH;
+ In_p->Target_p = In_p->Scratch;
+ In_p->ReqBuffOffset = 0;
+ } else {
+ if (A2_IsReceivedHeader(In_p)) {
+ if (A2_IsValidHeader(In_p->Scratch)) {
+ A2_DeserializeHeader(&In_p->Header, In_p->Scratch);
+ In_p->Packet_p = A2_Network_PacketAllocate(Communication_p, A2_COMMAND_BUFFER_SIZE);
+ VERIFY(NULL != In_p->Packet_p, E_FAILED_TO_FIND_COMM_BUFFER);
+ A2_DeserializeHeader(&In_p->Packet_p->Header, In_p->Scratch);
+ In_p->Packet_p->Flags = In_p->Packet_p->Flags | A2_BUF_HDR_CRC_OK;
+ In_p->Target_p = In_p->Packet_p->Buffer_p;
+ memcpy(In_p->Target_p, In_p->Scratch, A2_HEADER_LENGTH);
+ In_p->Target_p += A2_HEADER_LENGTH;
+ In_p->Packet_p->Payload_p = In_p->Packet_p->Buffer_p + A2_HEADER_LENGTH;
+
+ /* check for expected payload */
+ if (In_p->Header.DataLength != 0) {
+ A2_SET_INBOUND(In_p, A2_RECEIVE_PAYLOAD, In_p->Header.DataLength + A2_CRC_LENGTH);
+ } else {
+ (void)QUEUE(Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p, In_p->Packet_p);
+
+ /* Sync the header. */
+ In_p->Packet_p = NULL;
+ A2_RESET_INBOUND(In_p, A2_RECEIVE_HEADER);
+
+ if (A2_SPEEDFLASH_START != A2_SPEEDFLASH(Communication_p)->State) {
+ A2_SYNC_HEADER(In_p, A2_HEADER_LENGTH, In_p->Scratch);
+ }
+
+ C_(printf("a2_network.c (%d) ReqData(%d) RecData(%d) \n", __LINE__, In_p->ReqData, In_p->RecData);)
+ }
+ } else {
+ /* Sync the header. */
+ A2_RESET_INBOUND(In_p, A2_RECEIVE_HEADER);
+ A2_SYNC_HEADER(In_p, A2_HEADER_LENGTH, In_p->Scratch);
+ }
+ }
+ }
+
+ErrorExit:
+ return ReturnValue;
+}
+
+static ErrorCode_e A2_Network_ReceivePayload(Communication_t *Communication_p)
+{
+ A2_Inbound_t *In_p = &(A2_NETWORK(Communication_p)->Inbound);
+ A2_PacketMeta_t *Packet_p = In_p->Packet_p;
+
+ Packet_p->Communication_p = Communication_p;
+
+ if (HASH_NONE != Communication_p->CurrentFamilyHash) {
+ Communication_p->HashDevice_p->Calculate(OBJECT_HASH(Communication_p),
+ Communication_p->CurrentFamilyHash,
+ Packet_p->Buffer_p, Packet_p->Header.DataLength + A2_HEADER_LENGTH,
+ Packet_p->CRC, (HashCallback_t)A2_InHashCallback,
+ (void *)Packet_p);
+ } else {
+ Packet_p->Flags = Packet_p->Flags | A2_BUF_PAYLOAD_CRC_OK | A2_BUF_RX_READY;
+ (void)QUEUE((Packet_p->Communication_p), FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Inbound_p, Packet_p);
+ }
+
+ In_p->Packet_p = NULL;
+ A2_RESET_INBOUND(In_p, A2_RECEIVE_HEADER);
+ A2_SYNC_HEADER(In_p, A2_HEADER_LENGTH, In_p->Scratch);
+ return E_SUCCESS;
+}
+
+ErrorCode_e A2_Network_TransmiterHandler(Communication_t *Communication_p)
+{
+ ErrorCode_e ReturnValue = E_SUCCESS;
+ A2_Outbound_t *Out_p = &(A2_NETWORK(Communication_p)->Outbound);
+
+ if (Out_p->InLoad) {
+ return E_SUCCESS;
+ }
+
+ Out_p->InLoad = TRUE;
+
+ switch (Out_p->State) {
+ case A2_SEND_IDLE:
+ /* check retransmission count before send */
+ Out_p->Packet_p = (A2_PacketMeta_t *)QUEUE(Communication_p, FifoDequeue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p);
+
+ if (NULL != Out_p->Packet_p) {
+ if (Out_p->Packet_p->Resend < MAX_RESENDS) {
+ Out_p->Packet_p->Resend++;
+ /* get next packet for transmitting */
+ Out_p->State = A2_SEND_HEADER;
+ } else {
+ return E_RETRANSMITION_FAILED;
+ }
+ } else {
+ break;
+ }
+
+ /* FALLTHROUGH */
+ case A2_SEND_HEADER:
+
+ /* set next state before calling the communication device, to avoid race condition
+ where write callback is called before new state is set */
+ if (Out_p->Packet_p->Header.Protocol == PROTO_A2_ACK) {
+ Out_p->State = A2_SENDING_PAYLOAD;
+ } else {
+ Out_p->State = A2_SENDING_HEADER;
+ }
+
+ if (E_SUCCESS == Communication_p->CommunicationDevice_p->Write((Out_p->Packet_p->Buffer_p),
+ A2_HEADER_LENGTH, A2_Network_WriteCallback, Communication_p)) {
+ C_(printf("a2_network.c (%d) Header Sent to comm device! \n", __LINE__);)
+ } else {
+ Out_p->State = A2_SEND_HEADER;
+ C_(printf("a2_network.c (%d) Error sending header to comm device! \n", __LINE__);)
+ }
+
+ break;
+ case A2_SENDING_HEADER:
+ /* nothing to do, wait until sending is finished and state changed in write callback */
+ break;
+ case A2_SEND_PAYLOAD:
+ Out_p->State = A2_SENDING_PAYLOAD;
+
+ if (E_SUCCESS == Communication_p->CommunicationDevice_p->Write(
+ (Out_p->Packet_p->Buffer_p + A2_HEADER_LENGTH),
+ Out_p->Packet_p->Header.DataLength + A2_CRC_LENGTH,
+ A2_Network_WriteCallback, Communication_p)) {
+ C_(printf("a2_network.c (%d) Payload Sent to comm device! \n", __LINE__);)
+ } else {
+ Out_p->State = A2_SEND_PAYLOAD;
+ C_(printf("a2_network.c (%d) Error sending payload to comm device! \n", __LINE__);)
+ }
+
+ break;
+ case A2_SENDING_PAYLOAD:
+ /* nothing to do, wait until sending is finished and state changed when packet ACK is received */
+ break;
+ }
+
+ Out_p->InLoad = FALSE;
+
+ return ReturnValue;
+}
+
+static ErrorCode_e A2_Network_RegisterRetransmission(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p)
+{
+ ErrorCode_e ReturnValue = E_SUCCESS;
+
+ if (NULL == Packet_p->Timer_p->HandleFunction_p) {
+ Packet_p->Timer_p->HandleFunction_p = (HandleFunction_t)A2_Network_RetransmissionCallback;
+ Packet_p->Timer_p->Param_p = Communication_p;
+ }
+
+ A2_NETWORK(Communication_p)->RetransmissionContext.TimerKey = TIMER(Communication_p, TimerGet_Fn)(OBJECT_TIMER(Communication_p), Packet_p->Timer_p);
+ A2_NETWORK(Communication_p)->RetransmissionContext.Timeout = Packet_p->Timer_p->Time;
+
+ return ReturnValue;
+}
+
+static void A2_Network_RetransmissionCallback(Communication_t *Communication_p, const void *const Timer_p, void *Data_p)
+{
+ (void)QUEUE(Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p, Data_p);
+}
+
+static void A2_InHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p)
+{
+ IDENTIFIER_NOT_USED(Data_p);
+ IDENTIFIER_NOT_USED(Length);
+ A2_PacketMeta_t *Packet_p = (A2_PacketMeta_t *)Param_p;
+
+ if (memcmp(Hash_p, Packet_p->Buffer_p + A2_HEADER_LENGTH + Packet_p->Header.DataLength, sizeof(uint16)) == 0) {
+ Packet_p->Flags = Packet_p->Flags | A2_BUF_PAYLOAD_CRC_OK | A2_BUF_RX_READY;
+ (void)QUEUE((Packet_p->Communication_p), FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Inbound_p, Packet_p);
+ } else {
+ /* Invalid packet */
+ ErrorCode_e ReturnValue = E_GENERAL_FATAL_ERROR;
+
+ if (E_SUCCESS != (ReturnValue = A2_Network_PacketRelease((Communication_t *)Packet_p->Communication_p, Packet_p))) {
+ A2_NETWORK((Communication_t *)((A2_PacketMeta_t *)Param_p)->Communication_p)->Inbound.LCM_Error = ReturnValue;
+ }
+ }
+}
+
+#ifdef CFG_ENABLE_LOADER_TYPE
+static void A2_QueueCallback(const void *const Queue_p, void *Param_p)
+{
+ if (E_SUCCESS != A2_Network_TransmiterHandler((Communication_t *)Param_p)) {
+ A2_NETWORK((Communication_t *)Param_p)->Outbound.LCM_Error = E_GENERAL_COMMUNICATION_ERROR;
+ }
+}
+#endif //CFG_ENABLE_LOADER_TYPE
+
+/** @} */
+/** @} */
+/** @} */