summaryrefslogtreecommitdiff
path: root/lcmodule/source/cnh1605205_ldr_network_layer/source/r15_network_layer.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcmodule/source/cnh1605205_ldr_network_layer/source/r15_network_layer.c')
-rw-r--r--lcmodule/source/cnh1605205_ldr_network_layer/source/r15_network_layer.c931
1 files changed, 931 insertions, 0 deletions
diff --git a/lcmodule/source/cnh1605205_ldr_network_layer/source/r15_network_layer.c b/lcmodule/source/cnh1605205_ldr_network_layer/source/r15_network_layer.c
new file mode 100644
index 0000000..3b3a2fc
--- /dev/null
+++ b/lcmodule/source/cnh1605205_ldr_network_layer/source/r15_network_layer.c
@@ -0,0 +1,931 @@
+/*******************************************************************************
+ * Copyright (C) ST-Ericsson SA 2011
+ * License terms: 3-clause BSD license
+ ******************************************************************************/
+/**
+ * @addtogroup ldr_communication_serv
+ * @{
+ * @addtogroup r15_family
+ * @{
+ * @addtogroup ldr_network_layer
+ * @{
+ */
+
+/*******************************************************************************
+ * Includes
+ ******************************************************************************/
+#include "r_r15_network_layer.h"
+#include "r_basicdefinitions.h"
+#include <stdlib.h>
+#include "r_debug.h"
+#include "r_debug_macro.h"
+#include <string.h>
+#include "c_system.h"
+#include "r_r15_transport_layer.h"
+#include "r_r15_family.h"
+#include "r_communication_service.h"
+#include "r_r15_header.h"
+#include "r_bulk_protocol.h"
+#include "r_command_protocol.h"
+
+#ifdef CFG_ENABLE_MEASUREMENT_TOOL
+#include "r_measurement_tool.h"
+#include "r_time_utilities.h"
+#endif
+
+#define FREE_TRANSMITER 0
+#define BUSY_TRANSMITER 1
+
+#ifdef CFG_ENABLE_MEASUREMENT_TOOL
+extern Measurement_t *Measurement_p;
+#endif
+
+static PacketMeta_t PacketMetaInfo[COMMAND_BUFFER_COUNT + BULK_BUFFER_COUNT] = {0}; /* Packet Meta Info vector*/
+
+/*******************************************************************************
+ * Declaration of file local functions
+ ******************************************************************************/
+static ErrorCode_e R15_Network_ReceiveHeader(const Communication_t *const Communication_p);
+static ErrorCode_e R15_Network_ReceiveExtendedHeader(Communication_t *Communication_p);
+static ErrorCode_e R15_Network_ReceivePayload(Communication_t *Communication_p);
+static ErrorCode_e R15_Network_RegisterRetransmission(Communication_t *Communication_p, PacketMeta_t *Packet_p);
+static void R15_Network_RetransmissionCallback(Communication_t *Communication_p, const void *const Timer_p, void *Data_p);
+static void R15_InHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p);
+#ifdef CFG_ENABLE_LOADER_TYPE
+static void R15_QueueOutCallback(const void *const Queue_p, void *Param_p);
+static void R15_QueueInCallback(const void *const Queue_p, void *Param_p);
+#endif
+static PacketMeta_t *R15_Network_GetAvailableMetaPacket(void);
+
+
+/*******************************************************************************
+ * File scope types, constants and variables
+ ******************************************************************************/
+
+#define RESET_INBOUND(c, s) do { (c)->ReqData = 0; (c)->RecData = 0; (c)->ReqBuffOffset = 0; (c)->Target_p = NULL; (c)->State = (s); } while(0);
+#define SYNC_HEADER(c, d, t) do { (c)->ReqData = d; (c)->Target_p = t; } while(0);
+#define 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 r15 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 R15_Network_Initialize(Communication_t *Communication_p)
+{
+ memset(R15_NETWORK(Communication_p), 0, sizeof(R15_NetworkContext_t));
+
+ /* Simulate a finished read to get the inbound state-machine going. */
+ R15_Network_ReadCallback(NULL, 0, Communication_p);
+ R15_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, R15_QueueOutCallback, Communication_p);
+ (void)QUEUE(Communication_p, Fifo_SetCallback_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p, QUEUE_NONEMPTY, R15_QueueInCallback, Communication_p);
+#endif
+ R15_NETWORK(Communication_p)->Inbound.LCM_Error = E_SUCCESS;
+ R15_NETWORK(Communication_p)->Outbound.LCM_Error = E_SUCCESS;
+
+ return E_SUCCESS;
+}
+
+/*
+ * Shut down the r15 network layer.
+ *
+ * @param [in,out] Communication_p Communication module context.
+ *
+ * @retval E_SUCCESS After successful execution.
+ */
+ErrorCode_e R15_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)) {
+ PacketMeta_t *Packet_p = (PacketMeta_t *)QUEUE(Communication_p, FifoDequeue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p);
+ BulkExtendedHeader_t ExtendedHeader = {0};
+
+ R15_DeserializeBulkExtendedHeader(&ExtendedHeader, Packet_p->ExtendedHeader_p);
+
+ if (Packet_p->Header.Protocol != BULK_PROTOCOL || (ExtendedHeader.TypeFlags & MASK_BULK_COMMAND_SELECT) != CMD_BULK_DATA) {
+ ReturnValue = R15_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 = R15_Network_PacketRelease(Communication_p, (PacketMeta_t *)QUEUE(Communication_p, FifoDequeue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p));
+ }
+
+ErrorExit:
+ return ReturnValue;
+}
+
+
+/*
+ * Handler for received packets in R15 protocol 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 R15_Network_ReadCallback(const void *Data_p, const uint32 Length, void *Param_p)
+{
+ Communication_t *Communication_p = (Communication_t *)Param_p;
+
+ C_(printf("r15_network_layer.c (%d) RecLength(%d) RecBackupData (%d)\n", __LINE__, Length, R15_NETWORK(Communication_p)->Inbound.RecBackupData);)
+ R15_NETWORK(Communication_p)->Inbound.RecData = Length + R15_NETWORK(Communication_p)->Inbound.RecBackupData;
+ R15_NETWORK(Communication_p)->Inbound.RecBackupData = 0;
+
+ if (R15_NETWORK(Communication_p)->Inbound.ReqData == 0) {
+ ErrorCode_e ReturnValue = E_GENERAL_COMMUNICATION_ERROR;
+
+ switch (R15_NETWORK(Communication_p)->Inbound.State) {
+ case RECEIVE_HEADER:
+ ReturnValue = R15_Network_ReceiveHeader(Communication_p);
+ break;
+
+ case RECEIVE_EXTENDED_HEADER:
+ ReturnValue = R15_Network_ReceiveExtendedHeader(Communication_p);
+ break;
+
+ case RECEIVE_PAYLOAD:
+ ReturnValue = R15_Network_ReceivePayload(Communication_p);
+ break;
+
+ default:
+ R15_NETWORK(Communication_p)->Inbound.State = RECEIVE_HEADER;
+ R15_NETWORK(Communication_p)->Inbound.RecData = 0;
+ R15_NETWORK(Communication_p)->Inbound.ReqData = ALIGNED_HEADER_LENGTH;
+ R15_NETWORK(Communication_p)->Inbound.Target_p = R15_NETWORK(Communication_p)->Inbound.Scratch;
+ R15_NETWORK(Communication_p)->Inbound.LCM_Error = E_SUCCESS;
+ ReturnValue = E_SUCCESS;
+ break;
+ }
+
+#ifdef CFG_ENABLE_LOADER_TYPE
+ ReturnValue = R15_Network_ReceiverHandler(Communication_p);
+#endif
+
+ if (E_SUCCESS != ReturnValue) {
+ R15_NETWORK(Communication_p)->Inbound.State = RECEIVE_ERROR;
+ }
+
+ R15_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 R15_Network_ReceiverHandler(Communication_t *Communication_p)
+{
+ uint32 ReqData;
+ uint32 ReqBuffOffset = 0;
+ R15_Inbound_t *In_p = &(R15_NETWORK(Communication_p)->Inbound);
+
+ /* new data for receiving ? */
+ 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,
+ R15_Network_ReadCallback, Communication_p);
+ C_(printf("r15_network_layer.c (%d) ReqData(%d) RecData(%d)\n", __LINE__, In_p->ReqData, In_p->RecData);)
+ C_(printf("r15_network_layer.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;
+ R15_Network_ReadCallback(In_p->Target_p + In_p->ReqBuffOffset, ReqData, Communication_p);
+ In_p->RecData = 0;
+ }
+ } else {
+ ReqData = In_p->ReqData;
+ ReqBuffOffset = (uint32)(In_p->ReqBuffOffset);
+ In_p->ReqBuffOffset = 0;
+ In_p->ReqData = 0;
+ (void)Communication_p->CommunicationDevice_p->Read(In_p->Target_p + ReqBuffOffset, ReqData, R15_Network_ReadCallback, Communication_p);
+ C_(printf("r15_network_layer.c (%d) ReqData(%d) RecData(%d) \n", __LINE__, In_p->ReqData, In_p->RecData);)
+ C_(printf("r15_network_layer.c (%d) Communication_p->BackupCommBufferSize(%d) RecBackupData (%d)\n", __LINE__, Communication_p->BackupCommBufferSize, In_p->RecBackupData);)
+ In_p->RecData = 0;
+ }
+ }
+
+ /* check for receiver sinhronization */
+ if (In_p->State == RECEIVE_ERROR) {
+ In_p->ReqData = 0;
+ In_p->RecData = 0;
+ In_p->ReqBuffOffset = 0;
+ In_p->State = RECEIVE_HEADER;
+ (void)Communication_p->CommunicationDevice_p->Read(In_p->Target_p, ALIGNED_HEADER_LENGTH, R15_Network_ReadCallback, Communication_p);
+ }
+
+ return R15_NETWORK(Communication_p)->Inbound.LCM_Error;
+}
+
+ErrorCode_e R15_Network_TransmiterHandler(Communication_t *Communication_p)
+{
+ ErrorCode_e ReturnValue = E_SUCCESS;
+ R15_Outbound_t *Out_p = &(R15_NETWORK(Communication_p)->Outbound);
+ uint8 *HeaderStartInBuffer_p = NULL;
+ boolean IsBufferContinuous = FALSE;
+ boolean RegisterRetransmission = FALSE;
+ uint32 ContinuousBufferLength = 0;
+ uint32 ExtHdrLen = 0;
+ uint32 Aligned_Length = 0;
+
+ if (Out_p->InLoad) {
+ return E_SUCCESS;
+ }
+
+ Out_p->InLoad = TRUE;
+
+ switch (Out_p->State) {
+ case SEND_IDLE:
+ /* check retransmission count before send */
+ Out_p->Packet_p = (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 = SEND_HEADER;
+ } else {
+ //Do_CommunicationInternalErrorHandler(E_RETRANSMITION_FAILED);
+ return E_RETRANSMITION_FAILED;
+ }
+ } else {
+ break;
+ }
+
+ /* FALLTHROUGH */
+ case SEND_HEADER:
+ HeaderStartInBuffer_p = Out_p->Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER;
+
+ if (Out_p->Packet_p->Header.ExtendedHeaderLength == COMMAND_EXTENDED_HEADER_LENGTH) {
+ ExtHdrLen = ALIGNED_COMMAND_EXTENDED_HEADER_LENGTH;
+ } else {
+ ExtHdrLen = ALIGNED_BULK_EXTENDED_HEADER_LENGTH;
+ }
+
+ if ((HeaderStartInBuffer_p + ALIGNED_HEADER_LENGTH + ExtHdrLen) == Out_p->Packet_p->Payload_p) {
+ /* end of the header and beginning of the payload are same */
+ IsBufferContinuous = TRUE;
+ }
+
+ /* set next state before calling the communication device, to avoid race condition
+ where write callback is called before new state is set */
+ if (IsBufferContinuous || Out_p->Packet_p->Header.PayloadLength == 0) {
+ /* we have a packet without payload or header and payload are contained in one
+ continuous buffer so it can be sent with one write request */
+ ContinuousBufferLength = ALIGNED_HEADER_LENGTH + ExtHdrLen + Out_p->Packet_p->Header.PayloadLength;
+ ContinuousBufferLength = (ContinuousBufferLength + (ALIGN_SIZE - 1)) & (~(ALIGN_SIZE - 1));
+
+ Out_p->State = SENDING_PAYLOAD;
+ RegisterRetransmission = TRUE;
+ } else {
+ ContinuousBufferLength = ALIGNED_HEADER_LENGTH + ExtHdrLen;
+ Out_p->State = SENDING_HEADER;
+ }
+
+ if (E_SUCCESS == Communication_p->CommunicationDevice_p->Write((Out_p->Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER),
+ ContinuousBufferLength,
+ R15_Network_WriteCallback, Communication_p)) {
+ C_(printf("r15_network_layer.c (%d) Header Sent to comm device! \n", __LINE__);)
+ } else {
+ Out_p->State = SEND_HEADER;
+ RegisterRetransmission = FALSE;
+ C_(printf("r15_network_layer.c (%d) Error sending header to comm device! \n", __LINE__);)
+ }
+
+ break;
+ case SENDING_HEADER:
+ /* nothing to do, wait until sending is finished and state changed by write callback */
+ break;
+ case SEND_PAYLOAD:
+ Out_p->State = SENDING_PAYLOAD;
+
+ Aligned_Length = (Out_p->Packet_p->Header.PayloadLength + (ALIGN_SIZE - 1)) & (~(ALIGN_SIZE - 1));
+
+ if (E_SUCCESS == Communication_p->CommunicationDevice_p->Write(Out_p->Packet_p->Payload_p,
+ Aligned_Length,
+ R15_Network_WriteCallback, Communication_p)) {
+ RegisterRetransmission = TRUE;
+ C_(printf("r15_network_layer.c (%d) Payload Sent to comm device! \n", __LINE__);)
+ } else {
+ Out_p->State = SEND_PAYLOAD;
+ C_(printf("r15_network_layer.c (%d) Error sending payload to comm device! \n", __LINE__);)
+ }
+
+ break;
+ case SENDING_PAYLOAD:
+ /* nothing to do, wait until sending is finished and state changed by write callback */
+ break;
+ }
+
+ if (RegisterRetransmission) {
+ if (NULL != Out_p->Packet_p->Timer_p) {
+ C_(printf("r15_network_layer.c (%d) Register retransmission\n", __LINE__);)
+ (void)R15_Network_RegisterRetransmission(Communication_p, Out_p->Packet_p);
+ }
+ }
+
+ Out_p->InLoad = FALSE;
+
+ return ReturnValue;
+}
+
+/*
+ * 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 R15_Network_CancelRetransmission(const Communication_t *const Communication_p, uint32 UniqueKey)
+{
+ ErrorCode_e ReturnValue = E_NOT_FOUND_ELEMENT_IN_RETRANSMISSION_LIST;
+ uint32 Index = 0;
+
+ do {
+ if ((R15_NETWORK(Communication_p)->RetransmissionList[Index] != NULL) && (R15_NETWORK(Communication_p)->RetransmissionList[Index]->Key == UniqueKey)) {
+ (void)TIMER(Communication_p, TimerRelease_Fn)(OBJECT_TIMER(Communication_p), R15_NETWORK(Communication_p)->RetransmissionList[Index]->TimerKey);
+
+ free(R15_NETWORK(Communication_p)->RetransmissionList[Index]->Packet_p->Timer_p);
+ ReturnValue = R15_Network_PacketRelease(Communication_p, R15_NETWORK(Communication_p)->RetransmissionList[Index]->Packet_p);
+
+ if (E_SUCCESS != ReturnValue) {
+ A_(printf("r15_network_layer.c(%d): Packet release failed!\n", __LINE__);)
+ return ReturnValue;
+ }
+
+ free(R15_NETWORK(Communication_p)->RetransmissionList[Index]);
+ R15_NETWORK(Communication_p)->RetransmissionList[Index] = NULL;
+ R15_NETWORK(Communication_p)->RetransmissionListCount--;
+
+ for (; Index < R15_NETWORK(Communication_p)->RetransmissionListCount; Index++) {
+ R15_NETWORK(Communication_p)->RetransmissionList[Index] = R15_NETWORK(Communication_p)->RetransmissionList[Index+1];
+ }
+
+ R15_NETWORK(Communication_p)->RetransmissionList[Index] = NULL;
+ ReturnValue = E_SUCCESS;
+ break;
+ }
+
+ Index++;
+ } while (Index < R15_NETWORK(Communication_p)->RetransmissionListCount);
+
+ return ReturnValue;
+}
+
+/*
+ * Create unique key.
+ *
+ * This function combine the session number and protocol type in one
+ * unique key for command packet. For the bulk packet the unique key is the
+ * combination of protocol type, session number and command.
+ *
+ * @param [in] Packet_p Pointer to the packet.
+ * @param [in] ExternalKey External key for marking the packet for retransmision.
+ *
+ * @return Unique key.
+ */
+uint32 R15_Network_CreateUniqueKey(const PacketMeta_t *const Packet_p, const uint8 ExternalKey)
+{
+ uint32 Key = Packet_p->Header.Protocol;
+
+ if (Key == PROTO_COMMAND) {
+ return((Key << 16) | *(Packet_p->ExtendedHeader_p) & MASK_CLR_STATE);
+ } else {
+ return ((Key << 16) | ((*(Packet_p->ExtendedHeader_p) & 0x00FF) << 8) | ExternalKey);
+ }
+}
+
+
+/*
+ * Network packet allocation in R15 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.
+ */
+PacketMeta_t *R15_Network_PacketAllocate(const Communication_t *const Communication_p, int BufferSize)
+{
+ 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("r15_network_layer.c (%d): ** Buffer allocation fail! **\n", __LINE__);)
+ goto ErrorExit;
+ }
+
+ B_(printf("r15_network_layer.c (%d): Buffer allocate (0x%x)! **\n", __LINE__, (uint32)Buffer_p);)
+
+ /* packet meta info allocate, get free packet meta structure */
+
+ Meta_p = R15_Network_GetAvailableMetaPacket();
+
+ if (NULL == Meta_p) {
+ R15_NETWORK(Communication_p)->Inbound.LCM_Error = E_ALLOCATE_FAILED;
+ goto ErrorExit;
+ }
+
+ /* packet meta info setup */
+ C_(
+
+ if (BULK_BUFFER_SIZE > BufferSize)
+ printf("CmdBuffGet:%x\n", Buffer_p);
+ else {
+ printf("ChunkBuffGet:%x\n", Buffer_p);
+ })
+
+ Meta_p->Buffer_p = (uint8 *)Buffer_p;
+ Meta_p->BufferSize = BufferSize;
+ SET_PACKET_FLAGS(Meta_p, PACKET_ALLOCATION_STATE_MASK, BUF_ALLOCATED);
+
+ do {
+ if (NULL == R15_NETWORK(Communication_p)->MetaInfoList[BuffersNr]) {
+ R15_NETWORK(Communication_p)->MetaInfoList[BuffersNr] = Meta_p;
+ break;
+ }
+
+ BuffersNr ++;
+ } while (BuffersNr < (COMMAND_BUFFER_COUNT + BULK_BUFFER_COUNT));
+
+ErrorExit:
+ return Meta_p;
+}
+
+
+/*
+ * Network packet release in R15 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 R15_Network_PacketRelease(const Communication_t *const Communication_p, 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 == R15_NETWORK(Communication_p)->MetaInfoList[BuffersNr]) {
+ R15_NETWORK(Communication_p)->MetaInfoList[BuffersNr] = NULL;
+ /* release buffer */
+ B_(printf("r15_network_layer.c (%d): Buffer release (0x%x)! **\n", __LINE__, (uint32)(Meta_p->Buffer_p));)
+#ifndef CFG_ENABLE_LOADER_TYPE
+ ReturnValue = BUFFER(Communication_p, BufferRelease_Fn)(OBJECT_BUFFER(Communication_p), Meta_p->Buffer_p, Meta_p->BufferSize);
+ VERIFY(E_SUCCESS == ReturnValue, ReturnValue);
+ B_(printf("r15_network_layer.c (%d): Buffer released! **\n", __LINE__);)
+#else
+ C_(
+
+ if (BULK_BUFFER_SIZE > Meta_p->BufferSize)
+ printf("CmdBuffRel:%x\n", Meta_p->Buffer_p);
+ else {
+ printf("ChunkBuffRel:%x\n", 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("r15_network_layer.c (%d): Buffer released! **\n", __LINE__);)
+#endif
+
+ memset(Meta_p, 0, sizeof(PacketMeta_t));
+ break;
+ }
+
+ BuffersNr ++;
+ } while (BuffersNr < (COMMAND_BUFFER_COUNT + BULK_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 R15_Network_WriteCallback(const void *Data_p, const uint32 Length, void *Param_p)
+{
+ Communication_t *Communication_p = (Communication_t *)Param_p;
+ R15_Outbound_t *Out_p = &(R15_NETWORK(Communication_p)->Outbound);
+ BulkExtendedHeader_t ExtendedHeader = {0};
+ B_(printf("r15_network_layer.c (%d): Device write finished!! \n", __LINE__);)
+
+ if (SENDING_HEADER == Out_p->State) {
+ Out_p->State = SEND_PAYLOAD;
+ } else if (SENDING_PAYLOAD == Out_p->State) {
+ if (NULL == Out_p->Packet_p->Timer_p) {
+ if (Out_p->Packet_p->Header.Protocol == BULK_PROTOCOL) {
+ R15_DeserializeBulkExtendedHeader(&ExtendedHeader, Out_p->Packet_p->ExtendedHeader_p);
+ }
+
+ if (!((Out_p->Packet_p->Header.Protocol == BULK_PROTOCOL) && ((ExtendedHeader.TypeFlags & MASK_BULK_COMMAND_SELECT) == CMD_BULK_DATA))) {
+ (void)R15_Network_PacketRelease(Communication_p, Out_p->Packet_p);
+ }
+ }
+
+ Out_p->State = SEND_IDLE;
+ SET_PACKET_FLAGS(Out_p->Packet_p, PACKET_TX_STATE_MASK, BUF_TX_SENT);
+ }
+
+#ifdef CFG_ENABLE_LOADER_TYPE
+
+ if (E_SUCCESS != R15_Network_TransmiterHandler(Communication_p)) {
+ R15_NETWORK(Communication_p)->Outbound.LCM_Error = E_GENERAL_COMMUNICATION_ERROR;
+ }
+
+#endif
+}
+
+
+/*******************************************************************************
+ * Definition of internal functions
+ ******************************************************************************/
+
+static ErrorCode_e R15_Network_ReceiveHeader(const Communication_t *const Communication_p)
+{
+ R15_Inbound_t *In_p = &(R15_NETWORK(Communication_p)->Inbound);
+
+ if (In_p->RecData == 0) {
+ In_p->ReqData = ALIGNED_HEADER_LENGTH;
+ In_p->Target_p = In_p->Scratch;
+ } else {
+ if (R15_IsReceivedHeader(In_p)) {
+ if (R15_IsValidHeader(In_p->Scratch)) {
+ R15_DeserializeHeader(&In_p->Header, In_p->Scratch);
+
+ In_p->Target_p += ALIGNED_HEADER_LENGTH;
+ if (In_p->Header.ExtendedHeaderLength == COMMAND_EXTENDED_HEADER_LENGTH) {
+ SET_INBOUND(In_p, RECEIVE_EXTENDED_HEADER, ALIGNED_COMMAND_EXTENDED_HEADER_LENGTH);
+ } else {
+ SET_INBOUND(In_p, RECEIVE_EXTENDED_HEADER, ALIGNED_BULK_EXTENDED_HEADER_LENGTH);
+ }
+ } else {
+ A_(printf("Not valid header!\n");)
+ /* Sync the header. */
+ RESET_INBOUND(In_p, RECEIVE_HEADER);
+ SYNC_HEADER(In_p, ALIGNED_HEADER_LENGTH, In_p->Scratch);
+ }
+ }
+ else
+ {
+ uint32 Counter = 0;
+
+ A_(printf("Invalid header! ");)
+ for (Counter = 0; Counter < 16; Counter++)
+ {
+ A_(printf(" %02X", In_p->Scratch[Counter]);)
+ }
+ A_(printf("\n\n");)
+ }
+ }
+
+ return E_SUCCESS;
+}
+
+static ErrorCode_e R15_Network_ReceiveExtendedHeader(Communication_t *Communication_p)
+{
+ R15_Inbound_t *In_p = &(R15_NETWORK(Communication_p)->Inbound);
+ ErrorCode_e ReturnValue = E_SUCCESS;
+ R15_Header_t R15Header = {0};
+ BulkExtendedHeader_t BulkExtendedHeader = {0};
+ boolean IsValidHeader = FALSE;
+
+ VERIFY(NULL != In_p, E_GENERAL_FATAL_ERROR);
+
+ R15_DeserializeHeader(&R15Header, In_p->Scratch);
+ R15_DeserializeBulkExtendedHeader(&BulkExtendedHeader, In_p->Target_p);
+
+ IsValidHeader = R15_IsValidExtendedHeader(In_p->Target_p,
+ In_p->Header.ExtendedHeaderLength,
+ In_p->Header.ExtendedHeaderChecksum);
+
+ if (IsValidHeader) {
+ if (R15Header.Protocol == BULK_PROTOCOL &&
+ (BulkExtendedHeader.TypeFlags & MASK_BULK_COMMAND_SELECT) == CMD_BULK_DATA) {
+ In_p->Packet_p = R15_Network_PacketAllocate(Communication_p, BULK_BUFFER_SIZE);
+ } else {
+ In_p->Packet_p = R15_Network_PacketAllocate(Communication_p, COMMAND_BUFFER_SIZE);
+ }
+
+ VERIFY(NULL != In_p->Packet_p, E_FAILED_TO_FIND_COMM_BUFFER);
+
+ In_p->Packet_p->Header = R15Header;
+ In_p->Packet_p->ExtendedHeader_p = In_p->Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER + ALIGNED_HEADER_LENGTH;
+ SET_PACKET_FLAGS(In_p->Packet_p, PACKET_RX_STATE_MASK, BUF_HDR_CRC_OK);
+ if (In_p->Packet_p->Header.ExtendedHeaderLength == COMMAND_EXTENDED_HEADER_LENGTH) {
+ In_p->Packet_p->Payload_p = In_p->Packet_p->ExtendedHeader_p + ALIGNED_COMMAND_EXTENDED_HEADER_LENGTH;
+ } else {
+ In_p->Packet_p->Payload_p = In_p->Packet_p->ExtendedHeader_p + ALIGNED_BULK_EXTENDED_HEADER_LENGTH;
+ }
+ memcpy(In_p->Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER, &In_p->Packet_p->Header, HEADER_LENGTH);
+ memcpy(In_p->Packet_p->ExtendedHeader_p, In_p->Target_p, In_p->Header.ExtendedHeaderLength);
+
+ In_p->Target_p = In_p->Packet_p->Payload_p;
+
+ /* check for expected payload */
+ if (In_p->Packet_p->Header.PayloadLength != 0) {
+ uint32 Aligned_Size = 0;
+ Aligned_Size = (In_p->Packet_p->Header.PayloadLength + (ALIGN_SIZE - 1)) & (~(ALIGN_SIZE - 1));
+
+ SET_INBOUND(In_p, RECEIVE_PAYLOAD, Aligned_Size);
+ } else {
+#ifdef DISABLE_SECURITY
+ SET_PACKET_FLAGS(In_p->Packet_p, PACKET_RX_STATE_MASK, BUF_RX_READY);
+ (void)QUEUE(Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p, In_p->Packet_p);
+#else
+ PacketMeta_t *Packet_p = In_p->Packet_p;
+ Packet_p->Communication_p = Communication_p;
+ SET_PACKET_FLAGS(In_p->Packet_p, PACKET_RX_STATE_MASK, BUF_RX_READY);
+ // Copy the original packet checksum to avoid hash mismatch
+ memcpy(Packet_p->Hash, &Packet_p->Header.PayloadChecksum, 4);
+
+ Communication_p->HashDevice_p->Calculate(OBJECT_HASH(Communication_p),
+ HASH_NONE,
+ Packet_p->Payload_p, Packet_p->Header.PayloadLength,
+ Packet_p->Hash, (HashCallback_t)R15_InHashCallback,
+ (void *)Packet_p);
+#endif
+
+ In_p->Packet_p = NULL;
+ RESET_INBOUND(In_p, RECEIVE_HEADER);
+ SYNC_HEADER(In_p, ALIGNED_HEADER_LENGTH, In_p->Scratch);
+ C_(printf("r15_network_layer.c (%d) ReqData(%d) RecData(%d) \n", __LINE__, In_p->ReqData, In_p->RecData);)
+ }
+ } else {
+ RESET_INBOUND(In_p, RECEIVE_HEADER);
+ SYNC_HEADER(In_p, ALIGNED_HEADER_LENGTH, In_p->Scratch);
+ }
+
+ErrorExit:
+ return ReturnValue;
+}
+
+static ErrorCode_e R15_Network_ReceivePayload(Communication_t *Communication_p)
+{
+ R15_Inbound_t *In_p = &(R15_NETWORK(Communication_p)->Inbound);
+ PacketMeta_t *Packet_p = In_p->Packet_p;
+
+ Packet_p->Communication_p = Communication_p;
+ SET_PACKET_FLAGS(In_p->Packet_p, PACKET_RX_STATE_MASK, BUF_RX_READY);
+
+#ifndef CFG_ENABLE_LOADER_TYPE
+ Communication_p->CurrentFamilyHash = (HashType_e)Packet_p->Header.Flags;
+#endif
+
+ if (HASH_NONE != Packet_p->Header.Flags) {
+#ifdef CFG_ENABLE_MEASUREMENT_TOOL
+ if(In_p->Packet_p->Header.Protocol == BULK_PROTOCOL){
+ BulkExtendedHeader_t ExtendedHeader = {0};
+ R15_DeserializeBulkExtendedHeader(&ExtendedHeader, Packet_p->ExtendedHeader_p);
+
+ if ((ExtendedHeader.TypeFlags & MASK_BULK_COMMAND_SELECT) == CMD_BULK_DATA){
+ (void)MP(Measurement_p, ExtendedHeader.AcksChunk, START_HASHINGCHUNK_TIME);
+ }
+ }
+#endif
+ Communication_p->HashDevice_p->Calculate(OBJECT_HASH(Communication_p),
+ Communication_p->CurrentFamilyHash,
+ Packet_p->Payload_p, Packet_p->Header.PayloadLength,
+ Packet_p->Hash, (HashCallback_t)R15_InHashCallback,
+ (void *)Packet_p);
+ } else {
+ SET_PACKET_FLAGS(Packet_p, PACKET_RX_STATE_MASK, BUF_PAYLOAD_CRC_OK);
+ (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;
+ RESET_INBOUND(In_p, RECEIVE_HEADER);
+ SYNC_HEADER(In_p, ALIGNED_HEADER_LENGTH, In_p->Scratch);
+ return E_SUCCESS;
+}
+
+static ErrorCode_e R15_Network_RegisterRetransmission(Communication_t *Communication_p, PacketMeta_t *Packet_p)
+{
+ int i;
+ int Index;
+ ErrorCode_e ReturnValue = E_SUCCESS;
+ static RetransmissionContext_t *R_Ctx_p = NULL;
+
+ if (R15_NETWORK(Communication_p)->RetransmissionListCount < MAX_SIZE_RETRANSMISSION_LIST) {
+ if (NULL == Packet_p->Timer_p->HandleFunction_p) {
+ Packet_p->Timer_p->HandleFunction_p = (HandleFunction_t)R15_Network_RetransmissionCallback;
+ Packet_p->Timer_p->Param_p = Communication_p;
+ }
+
+ R_Ctx_p = (RetransmissionContext_t *)malloc(sizeof(RetransmissionContext_t));
+
+ if (NULL == R_Ctx_p) {
+ return E_ALLOCATE_FAILED;
+ }
+
+ R_Ctx_p->TimerKey = TIMER(Communication_p, TimerGet_Fn)(OBJECT_TIMER(Communication_p), Packet_p->Timer_p);
+ R_Ctx_p->Timeout = Packet_p->Timer_p->Time;
+ R_Ctx_p->Packet_p = Packet_p;
+ R_Ctx_p->Key = R15_Network_CreateUniqueKey(Packet_p, (uint8)(*(R_Ctx_p->Packet_p->ExtendedHeader_p + sizeof(uint16))));
+
+ Index = 0;
+ C_(printf("r15_network_layer.c (%d) Key(%d) TKey(%d) \n", __LINE__, R_Ctx_p->Key, R_Ctx_p->TimerKey);)
+
+ do {
+ if (NULL != R15_NETWORK(Communication_p)->RetransmissionList[Index]) {
+ if (R_Ctx_p->Timeout < TIMER(Communication_p, ReadTime_Fn)(OBJECT_TIMER(Communication_p), R15_NETWORK(Communication_p)->RetransmissionList[Index]->TimerKey)) {
+ i = R15_NETWORK(Communication_p)->RetransmissionListCount;
+
+ for (; Index < i; i--) {
+ R15_NETWORK(Communication_p)->RetransmissionList[i] = R15_NETWORK(Communication_p)->RetransmissionList[i-1];
+ }
+
+ R15_NETWORK(Communication_p)->RetransmissionList[Index] = R_Ctx_p;
+ R_Ctx_p = NULL;
+ R15_NETWORK(Communication_p)->RetransmissionListCount++;
+ break;
+ }
+
+ Index++;
+ } else {
+ R15_NETWORK(Communication_p)->RetransmissionList[Index] = R_Ctx_p;
+ R_Ctx_p = NULL;
+ R15_NETWORK(Communication_p)->RetransmissionListCount++;
+ break;
+ }
+ } while (Index < MAX_SIZE_RETRANSMISSION_LIST);
+ } else {
+ A_(printf("r15_network_layer.c (%d) ** Err: Retransmision List is full! ** \n", __LINE__);)
+ }
+
+ return ReturnValue;
+}
+
+
+static void R15_Network_RetransmissionCallback(Communication_t *Communication_p, const void *const Timer_p, void *Packet_p)
+{
+ uint32 Index = 0;
+
+ /* get first in list of packets for retransmission and remove */
+ if (NULL != R15_NETWORK(Communication_p)->RetransmissionList[Index]) {
+ free(R15_NETWORK(Communication_p)->RetransmissionList[Index]);
+ R15_NETWORK(Communication_p)->RetransmissionList[Index] = NULL;
+ }
+
+ if (R15_NETWORK(Communication_p)->RetransmissionListCount > 0) {
+ C_(printf("r15_network_layer.c (%d) RetransmissionListCount(%d) \n", __LINE__, R15_NETWORK(Communication_p)->RetransmissionListCount);)
+ R15_NETWORK(Communication_p)->RetransmissionListCount--;
+
+ for (; Index < R15_NETWORK(Communication_p)->RetransmissionListCount; Index++) {
+ R15_NETWORK(Communication_p)->RetransmissionList[Index] = R15_NETWORK(Communication_p)->RetransmissionList[Index+1];
+ }
+
+ R15_NETWORK(Communication_p)->RetransmissionList[Index] = NULL;
+
+ /* enqueue the packet for retransmission */
+ (void)QUEUE(Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p, Packet_p);
+ }
+}
+
+
+static void R15_InHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p)
+{
+ PacketMeta_t *Packet_p = (PacketMeta_t *)Param_p;
+
+#ifdef CFG_ENABLE_MEASUREMENT_TOOL
+ if(Packet_p->Header.Protocol == BULK_PROTOCOL){
+ BulkExtendedHeader_t ExtendedHeader = {0};
+ R15_DeserializeBulkExtendedHeader(&ExtendedHeader, Packet_p->ExtendedHeader_p);
+
+ if ((ExtendedHeader.TypeFlags & MASK_BULK_COMMAND_SELECT) == CMD_BULK_DATA){
+ (void)MP(Measurement_p, ExtendedHeader.AcksChunk, END_HASHINGCHUNK_TIME);
+ }
+ }
+#endif
+
+ if (memcmp(Hash_p, &Packet_p->Header.PayloadChecksum, 4) == 0) {
+ SET_PACKET_FLAGS(Packet_p, PACKET_RX_STATE_MASK, BUF_PAYLOAD_CRC_OK);
+ (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 = R15_Network_PacketRelease((Communication_t *)Packet_p->Communication_p, Packet_p))) {
+ R15_NETWORK((Communication_t *)Packet_p->Communication_p)->Inbound.LCM_Error = ReturnValue;
+ }
+ }
+}
+
+#ifdef CFG_ENABLE_LOADER_TYPE
+static void R15_QueueOutCallback(const void *const Queue_p, void *Param_p)
+{
+ if (E_SUCCESS != R15_Network_TransmiterHandler((Communication_t *)Param_p)) {
+ R15_NETWORK((Communication_t *)Param_p)->Outbound.LCM_Error = E_GENERAL_COMMUNICATION_ERROR;
+ }
+}
+
+static void R15_QueueInCallback(const void *const Queue_p, void *Param_p)
+{
+ ErrorCode_e ReturnValue = E_GENERAL_FATAL_ERROR;
+ Communication_t *Communication_p = (Communication_t *)Param_p;
+ PacketMeta_t *Packet_p = NULL;
+
+ while ((Packet_p = (PacketMeta_t *)QUEUE(Communication_p, FifoDequeue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p)) != NULL) {
+ switch (Packet_p->Header.Protocol) {
+ case PROTO_BULK:
+ ReturnValue = R15_Bulk_Process(Communication_p, Packet_p);
+
+ if (E_SUCCESS != ReturnValue) {
+ R15_NETWORK(Communication_p)->Inbound.LCM_Error = ReturnValue;
+ }
+
+ break;
+
+ case PROTO_COMMAND:
+ ReturnValue = R15_Command_Process(Communication_p, Packet_p);
+
+ if (E_SUCCESS != ReturnValue) {
+ R15_NETWORK(Communication_p)->Inbound.LCM_Error = ReturnValue;
+ }
+
+ break;
+
+ default:
+ R15_NETWORK(Communication_p)->Inbound.LCM_Error = E_SUCCESS;
+ break;
+ }
+ }
+}
+#endif
+
+static PacketMeta_t *R15_Network_GetAvailableMetaPacket(void)
+{
+ uint8 i = 0;
+ PacketMeta_t *PacketMeta_p = NULL;
+
+ do {
+ if (NULL == PacketMetaInfo[i].Buffer_p) {
+ PacketMeta_p = &PacketMetaInfo[i];
+ break;
+ }
+
+ i++;
+ } while (i < COMMAND_BUFFER_COUNT + BULK_BUFFER_COUNT);
+
+ return PacketMeta_p;
+}
+
+/** @} */
+/** @} */
+/** @} */