diff options
Diffstat (limited to 'lcmodule/source/cnh1606344_ldr_communication_module/source/communication_service.c')
-rw-r--r-- | lcmodule/source/cnh1606344_ldr_communication_module/source/communication_service.c | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/lcmodule/source/cnh1606344_ldr_communication_module/source/communication_service.c b/lcmodule/source/cnh1606344_ldr_communication_module/source/communication_service.c new file mode 100644 index 0000000..342cb1b --- /dev/null +++ b/lcmodule/source/cnh1606344_ldr_communication_module/source/communication_service.c @@ -0,0 +1,583 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include <string.h> +#include "error_codes.h" +#include <stdlib.h> +#include <stdio.h> +#include "r_debug.h" +#include "r_debug_macro.h" +#include "r_r15_family.h" +#include "r_r15_transport_layer.h" +#include "r_r15_network_layer.h" +#include "r_communication_service.h" +#include "r_basicdefinitions.h" +#include "r_memmory_utils.h" + +#ifdef CFG_ENABLE_A2_FAMILY +#include "r_a2_family.h" +#include "r_a2_transport.h" +#endif +#ifndef CFG_ENABLE_LOADER_TYPE +#include "r_protrom_family.h" +#include "r_z_family.h" +#include "r_protrom_transport.h" +#include "r_z_transport.h" +#endif + +/******************************************************************************* + * File scope types, constants and variables + ******************************************************************************/ +#define QUEUE_SIZE 32 + +Communication_t GlobalCommunication = {0}; +Communication_t* GlobalCommunication_p = &GlobalCommunication; + +static FamilyDescriptor_t ProtocolFamilies[] = { + { + R15_Family_Init, + R15_Family_Shutdown, + R15_Transport_Poll, + R15_Transport_Send, + R15_SetProtocolTimeouts, + R15_GetProtocolTimeouts, + R15_CancelReceiver + }, + { +#ifdef CFG_ENABLE_A2_FAMILY + A2_Family_Init, + A2_Family_Shutdown, + A2_Transport_Poll, + A2_Transport_Send, + NULL, + NULL, + A2_CancelReceiver +#else + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +#endif + }, +#ifndef CFG_ENABLE_LOADER_TYPE + { + // we do not support TI protocol family + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }, + { + Protrom_Family_Init, + Protrom_Family_Shutdown, + Protrom_Transport_Poll, + Protrom_Transport_Send, + NULL, + NULL, + Protrom_CancelReceiver + }, + { + Z_Family_Init, + Z_Family_Shutdown, + Z_Transport_Poll, + Z_Transport_Send, + NULL, + NULL, + Z_CancelReceiver + } +#endif +}; + +#define MAX_FAMILY (sizeof(ProtocolFamilies) / sizeof(ProtocolFamilies[0])) + +/******************************************************************************* + * Delaration of internal functions + ******************************************************************************/ + +static BuffersInterface_t *CreateBufferInterfaceHelpper(BuffersInterface_t *Buffers_p); +static TimersInterface_t *CreateTimerInterfaceHelpper(TimersInterface_t *Timers_p); +static QueueInterface_t *CreateQueueInterfaceHelpper(QueueInterface_t *Queue_p); + +static void DestroyBufferInterface(const Communication_t *const Communication_p); +static void DestroyTimerInterface(const Communication_t *const Communication_p); +static void DestroyQueueInterface(const Communication_t *const Communication_p); +FamilyDescriptor_t *GetFamily(Family_t Family); + +/******************************************************************************* + * Definition of external functions + ******************************************************************************/ + +/* + * Initialize an instance of the communication module. + * + * Given the initial family, already initialized hash device descriptor + * and communication device descriptor, a new instance of the + * communication module is created and bound to use the provided devices. + * + * @param [in,out] Communication_p Communication module context. + * @param [in] Family Initial protocol family. + * @param [in] HashDevice_p The device to use for checksum + * calculations and verifications. + * @param [in] *CommunicationDevice_p The device to use for network + * transmission. + * @param [in] CommandCallback_p Collback function for command handling. + * + * @retval E_SUCCESS If the module instance is successfully + * initialized. A protocol family dependant error + * code otherwise. + */ +ErrorCode_e Do_Communication_Initialize(void *Object_p, Communication_t **Communication_pp, Family_t Family, HashDevice_t *HashDevice_p, CommunicationDevice_t *CommunicationDevice_p, Do_CEH_Call_t CommandCallback_p, BuffersInterface_t *Buffers_p, TimersInterface_t *Timers_p, QueueInterface_t *Queue_p) +{ + ErrorCode_e ReturnValue = E_INVALID_INPUT_PARAMETERS; + Communication_t *Communication_p = NULL; + + VERIFY((NULL != HashDevice_p) && (NULL != CommunicationDevice_p), E_INVALID_INPUT_PARAMETERS); + +#ifdef CFG_ENABLE_COMMUNICATION_SINGLETON + Communication_p = GlobalCommunication_p; +#else + VERIFY(NULL != Communication_pp, E_INVALID_INPUT_PARAMETERS); + + Communication_p = (Communication_t *)malloc(sizeof(Communication_t)); + VERIFY(NULL != Communication_p, E_ALLOCATE_FAILED); + memset(Communication_p, 0, sizeof(Communication_t)); + + Communication_p->Object_p = Object_p; + *Communication_pp = Communication_p; +#endif + + Communication_p->Functions_p = (FunctionInterface_t *)malloc(sizeof(FunctionInterface_t)); + + VERIFY(NULL != Communication_p->Functions_p, E_ALLOCATE_FAILED); + + /* init buffer functions*/ + Communication_p->Functions_p->BufferFunctions_p = CreateBufferInterfaceHelpper(Buffers_p); + + VERIFY(NULL != Communication_p->Functions_p->BufferFunctions_p, E_FAILED_TO_ALLOCATE_COMM_BUFFER); + + /* init Timer functions*/ + Communication_p->Functions_p->TimerFunctions_p = CreateTimerInterfaceHelpper(Timers_p); + + VERIFY(NULL != Communication_p->Functions_p->TimerFunctions_p, E_FAILED_TO_INTIALIZE_TIMER_FUNCTIONS); + + /* init Queue functions*/ + Communication_p->Functions_p->QueueFunctions_p = CreateQueueInterfaceHelpper(Queue_p); + + VERIFY(NULL != Communication_p->Functions_p->QueueFunctions_p, E_FAILED_TO_INTIALIZE_QUEUE_FUNCTIONS); + + /* TODO: FIFO init can fail, but there's currently no way of detecting it */ + QUEUE(Communication_p, FifoCreate_Fn)(OBJECT_QUEUE(Communication_p), &Communication_p->Inbound_p, QUEUE_SIZE, NULL); + QUEUE(Communication_p, FifoCreate_Fn)(OBJECT_QUEUE(Communication_p), &Communication_p->Outbound_p, QUEUE_SIZE, NULL); + + Communication_p->CommunicationDevice_p = CommunicationDevice_p; + Communication_p->HashDevice_p = HashDevice_p; + Communication_p->HashDevice_p->Object_p = HashDevice_p->Object_p; + Communication_p->CurrentFamilyHash = HASH_NONE; + Communication_p->BackupCommBufferSize = 0; + + ReturnValue = Do_Communication_SetFamily(Communication_p, Family, CommandCallback_p); + + C_(printf("#---------------------------------------------------------\n");) + C_(printf("# Loader Communication Module Started!\n");) + C_(printf("#---------------------------------------------------------\n");) + +ErrorExit: + return ReturnValue; +} + +/* + * Shutdown an instance of the communication module. + * + * Shutdown the initialized protocol family, cancel current transmission and + * receiving data thru the communication device and shutdown the transport and + * network layer. + * + * @param [in,out] Communication_pp Communication module context. + * + * @retval E_SUCCESS If the module instance is successfully + * shut down. A protocol family dependant error + * code otherwise. + */ +ErrorCode_e Do_Communication_Shutdown(Communication_t **Communication_pp) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + Communication_t *Communication_p = NULL; + + VERIFY((NULL != Communication_pp) && (NULL != *Communication_pp), E_INVALID_INPUT_PARAMETERS); + + Communication_p = *Communication_pp; + + (void)Communication_p->CommunicationDevice_p->Cancel(Communication_p->CommunicationDevice_p); + Communication_p->HashDevice_p->Cancel(OBJECT_HASH(Communication_p), (void **)&Communication_p->HashDevice_p); + + if (NULL != Communication_p->Family_p) { + ReturnValue = Communication_p->Family_p->FamilyShutdown_fn(Communication_p); + } + + QUEUE(Communication_p, FifoDestroy_Fn)(OBJECT_QUEUE(Communication_p), &Communication_p->Inbound_p); + QUEUE(Communication_p, FifoDestroy_Fn)(OBJECT_QUEUE(Communication_p), &Communication_p->Outbound_p); + + DestroyBufferInterface(Communication_p); + DestroyTimerInterface(Communication_p); + DestroyQueueInterface(Communication_p); + free(Communication_p->Functions_p); + + memset(Communication_p, 0, sizeof(Communication_t)); + + if (NULL != Communication_p->BackupCommBuffer_p) { + free(Communication_p->BackupCommBuffer_p); + Communication_p->BackupCommBuffer_p = NULL; + Communication_p->BackupCommBufferSize = 0; + } + + free(Communication_p); + Communication_p = NULL; + *Communication_pp = NULL; + +ErrorExit: + return ReturnValue; +} + +/* + * Change the current protocol family. + * + * Shuts down the old protocol family and initializes the new one. + * + * @param [in] Communication_p Communication module context. + * @param [in] Family New protocol family identifier. + * @param [in] CEHCallback Callback that will handle the commands. + * + * @retval E_SUCCESS If the family is successfully changed. A + * protocol family dependant error code otherwise. + */ +ErrorCode_e Do_Communication_SetFamily(Communication_t *Communication_p, Family_t Family, Do_CEH_Call_t CEHCallback) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + FamilyDescriptor_t *Family_p = GetFamily(Family); + + VERIFY(NULL != Family_p, E_INVALID_INPUT_PARAMETERS); + + if (NULL != Communication_p->Family_p) { + (void)Communication_p->CommunicationDevice_p->Cancel(Communication_p); + ReturnValue = Communication_p->Family_p->FamilyShutdown_fn(Communication_p); + + VERIFY(E_SUCCESS == ReturnValue, ReturnValue); + } + + Communication_p->Family_p = Family_p; + Communication_p->Do_CEH_Call_Fn = CEHCallback; + + ReturnValue = Communication_p->Family_p->FamilyInit_fn(Communication_p); +ErrorExit: + return ReturnValue; +} + + +/* + * Poll the network for inbound packets. + * + * When a packet is received it is put on the inbound queue. This + * function should be called whenever there is time to handle a new + * packet. It passes all the elements in the queue to the family + * specific polling function, one by one. + * + * @param [in] Communication_p Communication module context. + * + * + * @retval E_SUCCESS If all packets are successfully handled. A + * protocol family dependant error code otherwise. + */ +ErrorCode_e Do_Communication_Poll(Communication_t *Communication_p) +{ + ErrorCode_e ReturnValue = E_GENERAL_COMMUNICATION_ERROR; + + VERIFY(NULL != Communication_p->Family_p, ReturnValue); + + ReturnValue = Communication_p->Family_p->Process_fn(Communication_p); + +ErrorExit: + return ReturnValue; +} + +/* + * Function for sending packet. + * + * @param [in] Communication_p Communication module context. + * @param [in] InputData_p Pointer to the data for tranmission. + * + * @retval E_SUCCESS After successful execution. + * @retval E_FAILED_TO_ALLOCATE_COMM_BUFFER Failed to allocate communication + * buffer. + */ +ErrorCode_e Do_Communication_Send(Communication_t *Communication_p, void *InputData_p) +{ + ErrorCode_e ReturnValue = E_GENERAL_COMMUNICATION_ERROR; + + VERIFY(NULL != Communication_p->Family_p, ReturnValue); + + (void)Communication_p->Family_p->Send_fn(Communication_p, InputData_p); + + ReturnValue = E_SUCCESS; + +ErrorExit: + return ReturnValue; +} + +/* + * Function for setting the timeouts in the protocols. + * + * Timeouts that should be set depend of the protocol family. Some protocol + * family do not have timeouts. + * + * @param [in] Communication_p Communication module context. + * @param [in] TimeoutData_p Pointer to the data with all timeouts. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e Do_Communication_SetProtocolTimeouts(Communication_t *Communication_p, void *TimeoutData_p) +{ + ErrorCode_e ReturnValue = E_GENERAL_COMMUNICATION_ERROR; + + VERIFY(NULL != Communication_p->Family_p, ReturnValue); + + (void)Communication_p->Family_p->SetProtocolTimeouts_fn(Communication_p, TimeoutData_p); + + ReturnValue = E_SUCCESS; + +ErrorExit: + return ReturnValue; +} + +/* + * Function for getting the timeouts in the protocols. + * + * Timeouts that should be get depend of the protocol family. Some protocol + * family do not have timeouts. + * + * @param [in] Communication_p Communication module context. + * @param [out] TimeoutData_p Return data with all timeouts. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e Do_Communication_GetProtocolTimeouts(Communication_t *Communication_p, void *TimeoutData_p) +{ + ErrorCode_e ReturnValue = E_GENERAL_COMMUNICATION_ERROR; + + VERIFY(NULL != Communication_p->Family_p, ReturnValue); + + (void)Communication_p->Family_p->GetProtocolTimeouts_fn(Communication_p, TimeoutData_p); + + ReturnValue = E_SUCCESS; + +ErrorExit: + return ReturnValue; +} + +/* + * Function for getting the communication device for the given LCM instance. + * + * If communication is Singleton the function can be called with NULL pointer + * for Communication_p. + * + * @param [in] Communication_p Communication module context. + * @param [out] CommunicationDevice_pp Pointer to the initialized communication + * device for the given LCM context. + * + * @retval E_SUCCESS After successful execution. + * @retval E_INVALID_INPUT_PARAMTERS In case when communicaiton is not Singleton + * and Communication_p is NULL pointer. + */ +ErrorCode_e Do_Communication_GetCommunicationDevice(Communication_t *Communication_p, CommunicationDevice_t** CommunicationDevice_pp) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + VERIFY(NULL != Communication_p && CommunicationDevice_pp != NULL, E_INVALID_INPUT_PARAMETERS); + + *CommunicationDevice_pp = Communication_p->CommunicationDevice_p; + +ErrorExit: + return ReturnValue; +} + +/* + * Function for setting the communication device for the given LCM instance. + * + * If communication is Singleton the function can be called with NULL pointer + * for Communication_p. + * + * @param [in] Communication_p Communication module context. + * @param [out] CommunicationDevice_p Pointer to the initialized communication + * device to be set for the given LCM context. + * + * @retval E_SUCCESS After successful execution. + * @retval E_INVALID_INPUT_PARAMTERS In case when communicaiton is not Singleton + * and Communication_p is NULL pointer. + */ +ErrorCode_e Do_Communication_SetCommunicationDevice(Communication_t *Communication_p, CommunicationDevice_t* CommunicationDevice_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + VERIFY(NULL != Communication_p && CommunicationDevice_p != NULL, E_INVALID_INPUT_PARAMETERS); + + Communication_p->CommunicationDevice_p = CommunicationDevice_p; + +ErrorExit: + return ReturnValue; +} + +/* + * Cancek Receiving new packets + * + * @param [in] Communication_p Communication module context. + * @param [in] PacketsBeforeReceiverStop Number of packets to be send before stopping the receiver. + * + * @retval E_SUCCESS If all packets are successfully handled. A + * protocol family dependant error code otherwise. + */ +ErrorCode_e Do_Communication_Cancel_Receiver(Communication_t *Communication_p, uint8 PacketsBeforeReceiverStop) +{ + ErrorCode_e ReturnValue = E_GENERAL_COMMUNICATION_ERROR; + + VERIFY(NULL != Communication_p->Family_p, ReturnValue); + + ReturnValue = Communication_p->Family_p->CancelReceiver_fn(Communication_p, PacketsBeforeReceiverStop); + +ErrorExit: + return ReturnValue; +} + +void Do_CommunicationInternalErrorHandler(const ErrorCode_e IntError) +{ +#ifndef PRINT_A_ + IDENTIFIER_NOT_USED(IntError); +#endif + A_(printf("# Error Code: 0x%X !\n", IntError);) + A_(printf("# Loader stoped!\n");) + A_(printf("#---------------------------------------------------------\n");) + + /* coverity[no_escape] */ + while (1); +} + +/******************************************************************************* + * Definition of internal functions + ******************************************************************************/ +static BuffersInterface_t *CreateBufferInterfaceHelpper(BuffersInterface_t *Buffers_p) +{ + BuffersInterface_t *BufferFunctions_p = (BuffersInterface_t *)malloc(sizeof(BuffersInterface_t)); + + if (NULL == BufferFunctions_p) { + return NULL; + } + + BufferFunctions_p->BuffersInit_Fn = Buffers_p->BuffersInit_Fn; + BufferFunctions_p->BufferAllocate_Fn = Buffers_p->BufferAllocate_Fn; + BufferFunctions_p->BufferRelease_Fn = Buffers_p->BufferRelease_Fn; + BufferFunctions_p->BuffersAvailable_Fn = Buffers_p->BuffersAvailable_Fn; + BufferFunctions_p->BuffersDeinit_Fn = Buffers_p->BuffersDeinit_Fn; +#ifndef CFG_ENABLE_LOADER_TYPE + BufferFunctions_p->Object_p = Buffers_p->Object_p; +#endif + + return BufferFunctions_p; +} + +static TimersInterface_t *CreateTimerInterfaceHelpper(TimersInterface_t *Timers_p) +{ + TimersInterface_t *TimerFunctions_p = (TimersInterface_t *)malloc(sizeof(TimersInterface_t)); + + if (NULL == TimerFunctions_p) { + return NULL; + } + + TimerFunctions_p->TimersInit_Fn = Timers_p->TimersInit_Fn; + TimerFunctions_p->TimerGet_Fn = Timers_p->TimerGet_Fn; + TimerFunctions_p->TimerRelease_Fn = Timers_p->TimerRelease_Fn; + TimerFunctions_p->ReadTime_Fn = Timers_p->ReadTime_Fn; + TimerFunctions_p->GetSystemTime_Fn = Timers_p->GetSystemTime_Fn; +#ifndef CFG_ENABLE_LOADER_TYPE + TimerFunctions_p->Object_p = Timers_p->Object_p; +#endif + + return TimerFunctions_p; +} + +static QueueInterface_t *CreateQueueInterfaceHelpper(QueueInterface_t *Queue_p) +{ + QueueInterface_t *QueueFunctions_p = (QueueInterface_t *)malloc(sizeof(QueueInterface_t)); + + if (NULL == QueueFunctions_p) { + return NULL; + } + + QueueFunctions_p->FifoCreate_Fn = Queue_p->FifoCreate_Fn; + QueueFunctions_p->FifoDestroy_Fn = Queue_p->FifoDestroy_Fn; + QueueFunctions_p->FifoEnqueue_Fn = Queue_p->FifoEnqueue_Fn; + QueueFunctions_p->FifoDequeue_Fn = Queue_p->FifoDequeue_Fn; + QueueFunctions_p->Fifo_SetCallback_Fn = Queue_p->Fifo_SetCallback_Fn; + QueueFunctions_p->Fifo_IsEmpty_Fn = Queue_p->Fifo_IsEmpty_Fn; + QueueFunctions_p->Fifo_IsMember_Fn = Queue_p->Fifo_IsMember_Fn; + QueueFunctions_p->Fifo_GetNrOfElements_Fn = Queue_p->Fifo_GetNrOfElements_Fn; + + QueueFunctions_p->RFifoCreate_Fn = Queue_p->RFifoCreate_Fn; + QueueFunctions_p->RFifoDestroy_Fn = Queue_p->RFifoDestroy_Fn; + QueueFunctions_p->RFifoEnqueue_Fn = Queue_p->RFifoEnqueue_Fn; + QueueFunctions_p->RFifoDequeue_Fn = Queue_p->RFifoDequeue_Fn; + QueueFunctions_p->RFifo_SetCallback_Fn = Queue_p->RFifo_SetCallback_Fn; + QueueFunctions_p->RFifo_IsEmpty_Fn = Queue_p->RFifo_IsEmpty_Fn; + QueueFunctions_p->RFifo_IsMember_Fn = Queue_p->RFifo_IsMember_Fn; + QueueFunctions_p->RFifo_GetNrOfElements_Fn = Queue_p->RFifo_GetNrOfElements_Fn; + +#ifndef CFG_ENABLE_LOADER_TYPE + QueueFunctions_p->Object_p = Queue_p->Object_p; +#endif + return QueueFunctions_p; +} + +static void DestroyBufferInterface(const Communication_t *const Communication_p) +{ + if (NULL != Communication_p->Functions_p->BufferFunctions_p) { + free(Communication_p->Functions_p->BufferFunctions_p); + Communication_p->Functions_p->BufferFunctions_p = NULL; + } +} + +static void DestroyTimerInterface(const Communication_t *const Communication_p) +{ + if (NULL != Communication_p->Functions_p->TimerFunctions_p) { + free(Communication_p->Functions_p->TimerFunctions_p); + Communication_p->Functions_p->TimerFunctions_p = NULL; + } +} + +static void DestroyQueueInterface(const Communication_t *const Communication_p) +{ + if (NULL != Communication_p->Functions_p->QueueFunctions_p) { + free(Communication_p->Functions_p->QueueFunctions_p); + Communication_p->Functions_p->QueueFunctions_p = NULL; + } +} + +FamilyDescriptor_t *GetFamily(Family_t Family) +{ + uint32 IntFamily = (uint32)Family; + + if (IntFamily > (MAX_FAMILY - 1)) { + return NULL; + } + + return (FamilyDescriptor_t *)&ProtocolFamilies[Family]; +} + +/** @}*/ |