diff options
Diffstat (limited to 'lcmodule/source/cnh1605204_ldr_transport_layer/source')
9 files changed, 3095 insertions, 0 deletions
diff --git a/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_protocol.c b/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_protocol.c new file mode 100644 index 0000000..a26b677 --- /dev/null +++ b/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_protocol.c @@ -0,0 +1,309 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + * @addtogroup a2_family + * @{ + * @addtogroup a2_protocol + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include "t_basicdefinitions.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "r_communication_service.h" +#include "r_a2_family.h" +#include "r_a2_network.h" +#include "r_a2_transport.h" +#include "t_a2_header.h" +#include "t_a2_protocol.h" +#include "r_a2_protocol.h" +#include "t_security_algorithms.h" +#include "r_command_protocol.h" +#include "r_debug.h" +#include "r_debug_macro.h" +#include "r_serialization.h" +#include "r_memmory_utils.h" + +/******************************************************************************* + * File scope types, constants and variables + ******************************************************************************/ +/** Holding the sequence number for each communication device.*/ +uint8 A2_SequenceNr = 0; + +/******************************************************************************* + * Declaration of file local functions + ******************************************************************************/ +static ErrorCode_e ProcessAcknowledgement(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p); +static ErrorCode_e ProcessCommand(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p); +static ErrorCode_e ProcessGeneralResponse(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p_p); +static ErrorCode_e ProcessControlMessage(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p); +static ErrorCode_e SendAcknowledge(Communication_t *Communication_p, const A2_PacketMeta_t *const Packet_p); +static ErrorCode_e DispatchCommand(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p, A2_CommandData_t CmdData); + +/******************************************************************************* + * Definition of external functions + ******************************************************************************/ + +/* + * Sends command packet with command protocol. + * + * @param [in] Communication_p Communication module context. + * @param [in] CmdData_p Pointer to the command data. + * + * @retval E_SUCCESS After successful execution. + * @retval E_INVALID_INPUT_PARAMETERS If CmdData_p is NULL. + */ +ErrorCode_e Do_A2_Command_Send(Communication_t *Communication_p, A2_CommandData_t *CmdData_p) +{ + A2_Header_t Header = {0}; + A2_SendData_LP_t Param; + + if (NULL == CmdData_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + Param.Header_p = &Header; + Param.Payload_p = CmdData_p->Payload.Data_p; + + Header.HeaderPattern = A2_HEADER_PATTERN; + Header.Protocol = PROTO_A2; + Header.SourceAddress = 0x00; + Header.DestinationAddress = CmdData_p->DestAddress; + Header.SequenceNumber = ++A2_SequenceNr; + Header.DataLength = CmdData_p->Payload.Size; + + Param.Time = 0xFFFFFFFF; //ACK_TIMEOUT_IN_MS; + Param.TimerCallBackFn_p = NULL; //NOTE: the timer will be assigned in "A2_Transport_Send" + + C_(printf("a2_protocol.c (%d): A2_Transport_Send! Type:%d SequenceNr:%d Command:%d CommandGroup:%d\n", __LINE__, CmdData_p->Type, Header.SequenceNumber, CmdData_p->ApplicationNr, CmdData_p->CommandNr);) + + return A2_Transport_Send(Communication_p, &Param); +} + +/* + * Decode received command. + * + * @param [in] Communication_p Communication module context. + * @param [in] Packet_p Pointer to the received buffer. + * + * @retval E_SUCCESS After successful execution. + * @retval E_INVALID_INPUT_PARAMETERS if Packet_p is NULL. + */ +ErrorCode_e A2_Command_Process(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + switch (((A2_PacketMeta_t *)Packet_p)->Header.Protocol) { + case PROTO_CTRL_MSG: + ReturnValue = ProcessControlMessage(Communication_p, Packet_p); + break; + + case PROTO_A2: + + if (0xFF == *(Packet_p->Payload_p + 1)) { + ReturnValue = ProcessGeneralResponse(Communication_p, Packet_p); + } else { + ReturnValue = ProcessCommand(Communication_p, Packet_p); + } + + break; + + case PROTO_A2_ACK: + ReturnValue = ProcessAcknowledgement(Communication_p, Packet_p); + break; + + default: + ReturnValue = E_SUCCESS; + break; + } + + return ReturnValue; +} + +/******************************************************************************* + * Definition of internal functions + ******************************************************************************/ +static ErrorCode_e ProcessControlMessage(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p) +{ + A2_CommandData_t CmdData = {0}; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + void *Tmp_Buffer_p = Packet_p->Payload_p; + + CmdData.Type = A2_CONTROL_MESSAGE; + CmdData.ApplicationNr = 0x10; + CmdData.CommandNr = get_uint8(&Tmp_Buffer_p); + CmdData.SessionNr = (uint16)(Packet_p->Header.SequenceNumber); + CmdData.Payload.Size = Packet_p->Header.DataLength; + CmdData.Payload.Data_p = NULL; + + if (0 != CmdData.Payload.Size) { + CmdData.Payload.Data_p = (uint8 *)malloc(Packet_p->Header.DataLength); + + if (NULL == CmdData.Payload.Data_p) { + return E_ALLOCATE_FAILED; + } + + memcpy(CmdData.Payload.Data_p, Packet_p->Payload_p, Packet_p->Header.DataLength); + } + + return DispatchCommand(Communication_p, Packet_p, CmdData); +} + +static ErrorCode_e ProcessAcknowledgement(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p) +{ + ErrorCode_e ReturnValue = E_GENERAL_FATAL_ERROR; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + B_(printf("a2_protocol.c (%d): Received Acknowledge!\n", __LINE__);) + ReturnValue = A2_Network_CancelRetransmission(Communication_p, Packet_p->Header.SequenceNumber); + VERIFY(E_SUCCESS == ReturnValue, ReturnValue); + ReturnValue = A2_Network_PacketRelease(Communication_p, Packet_p); + + if (A2_SPEEDFLASH_START == A2_SPEEDFLASH(Communication_p)->State) { + Communication_p->CommunicationDevice_p->Cancel(Communication_p); + A2_SPEEDFLASH(Communication_p)->State = A2_SPEEDFLASH_ACTIVE; + A2_SPEEDFLASH(Communication_p)->InboundState = A2_SPEEDFLASH_READ_REQ; + } + +ErrorExit: + return ReturnValue; +} + +static ErrorCode_e ProcessCommand(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p) +{ + ErrorCode_e ReturnValue; + A2_CommandData_t CmdData = {0}; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + void *Tmp_Buffer_p = Packet_p->Payload_p; + + CmdData.Type = A2_COMMAND; + CmdData.ApplicationNr = get_uint8(&Tmp_Buffer_p); + CmdData.CommandNr = get_uint8(&Tmp_Buffer_p); + CmdData.SessionNr = (uint16)(Packet_p->Header.SequenceNumber); + CmdData.Payload.Size = Packet_p->Header.DataLength; + CmdData.Payload.Data_p = NULL; + + if (0 != CmdData.Payload.Size) { + CmdData.Payload.Data_p = (uint8 *)malloc(Packet_p->Header.DataLength); + + if (NULL == CmdData.Payload.Data_p) { + return E_ALLOCATE_FAILED; + } + + memcpy(CmdData.Payload.Data_p, Packet_p->Payload_p, Packet_p->Header.DataLength); + } + + ReturnValue = SendAcknowledge(Communication_p, Packet_p); + + if (E_SUCCESS != ReturnValue) { + BUFFER_FREE(CmdData.Payload.Data_p); + return ReturnValue; + } + + return DispatchCommand(Communication_p, Packet_p, CmdData); +} + +static ErrorCode_e ProcessGeneralResponse(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p) +{ + ErrorCode_e ReturnValue; + A2_CommandData_t CmdData = {0}; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + void *Tmp_Buffer_p = Packet_p->Payload_p; + + CmdData.Type = A2_GENERAL_RESPONSE; + CmdData.ApplicationNr = get_uint8(&Tmp_Buffer_p); + // skip 0xFF byte signifying GR + skip_uint8(&Tmp_Buffer_p); + // skip more packets field + // TODO check how we should handle situation when GR contains more packets + skip_uint8(&Tmp_Buffer_p); + CmdData.CommandNr = get_uint8(&Tmp_Buffer_p); + CmdData.SessionNr = (uint16)(Packet_p->Header.SequenceNumber); + CmdData.Payload.Size = Packet_p->Header.DataLength; + CmdData.Payload.Data_p = NULL; + + if (0 != CmdData.Payload.Size) { + CmdData.Payload.Data_p = (uint8 *)malloc(Packet_p->Header.DataLength); + + if (NULL == CmdData.Payload.Data_p) { + return E_ALLOCATE_FAILED; + } + + memcpy(CmdData.Payload.Data_p, Packet_p->Payload_p, Packet_p->Header.DataLength); + } + + ReturnValue = SendAcknowledge(Communication_p, Packet_p); + + if (E_SUCCESS != ReturnValue) { + BUFFER_FREE(CmdData.Payload.Data_p); + return ReturnValue; + } + + return DispatchCommand(Communication_p, Packet_p, CmdData); +} + + +static ErrorCode_e DispatchCommand(Communication_t *Communication_p, A2_PacketMeta_t *Packet_p, A2_CommandData_t CmdData) +{ + ErrorCode_e ReturnValue; + + ReturnValue = A2_Network_PacketRelease(Communication_p, Packet_p); + + ReturnValue = Communication_p->Do_CEH_Call_Fn(OBJECT_CEH_CALL(Communication_p), (CommandData_t *)&CmdData); + + if (NULL != CmdData.Payload.Data_p) { + free(CmdData.Payload.Data_p); + } + + return ReturnValue; +} + +static ErrorCode_e SendAcknowledge(Communication_t *Communication_p, const A2_PacketMeta_t *const Packet_p) +{ + A2_Header_t Header = {0}; + A2_SendData_LP_t Param; + + Header.HeaderPattern = A2_HEADER_PATTERN; + Header.Protocol = PROTO_A2_ACK; + Header.SourceAddress = 0x00; + Header.DestinationAddress = Packet_p->Header.SourceAddress; + Header.SequenceNumber = Packet_p->Header.SequenceNumber; + + Param.Header_p = &Header; + Param.Payload_p = NULL; + Param.Time = 0; + Param.TimerCallBackFn_p = NULL; + + return A2_Transport_Send(Communication_p, &Param); +} + +/** @} */ +/** @} */ +/** @} */ diff --git a/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_speedflash.c b/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_speedflash.c new file mode 100755 index 0000000..b411027 --- /dev/null +++ b/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_speedflash.c @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + * @addtogroup a2_family + * @{ + * @addtogroup a2_protocol + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include "t_basicdefinitions.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "r_communication_service.h" +#include "r_debug.h" +#include "r_debug_macro.h" +#include "r_a2_speedflash.h" +#include "t_a2_family.h" +#include "r_a2_family.h" +#include "r_a2_network.h" + +/******************************************************************************* + * Declaration of file local functions + ******************************************************************************/ +static void A2_Speedflash_WriteCallback(const void *Data_p, const uint32 Length, void *Param_p); +static void A2_Speedflash_ReadCallback(const void *Data_p, const uint32 Length, void *Param_p); + +/** + * Set the LCM in A2 Speedflash Mode. + * + * @param [in] Communication_p Communication module context. + * @param [in] State State of the speedflash (TRUE - on, FALSE - off). + * + * @retval E_SUCCESS After successful execution. + * @retval + */ +void Do_A2_Speedflash_Start(Communication_t *Communication_p) +{ + A2_SPEEDFLASH(Communication_p)->State = A2_SPEEDFLASH_START; + + C_(printf("a2_speedflash.c (%d): Do_A2_Speedflash_Start\n", __LINE__);) +} + +void Do_A2_Speedflash_SetLastBlock(Communication_t *Communication_p) +{ + A2_SPEEDFLASH(Communication_p)->LastBlock = TRUE; + + C_(printf("a2_speedflash.c (%d): Do_A2_Speedflash_SetLastBlock\n", __LINE__);) +} + +/** + * Writes A2 speedflash sub-block on the comm device. + * + * @param [in] Communication_p Communication module context. + * @param [in] Buffer Buffer containing the data of the sub-block. + * @param [in] BufferSize Size of the speedflash sub-blocks. + * + * @retval E_SUCCESS After successful execution. + * @retval + */ +ErrorCode_e Do_A2_Speedflash_WriteBlock(Communication_t *Communication_p, const void *Buffer, const uint32 BufferSize) +{ + A2_SPEEDFLASH(Communication_p)->Outbound_p = (void *)Buffer; + A2_SPEEDFLASH(Communication_p)->OutboundSize = BufferSize; + + C_(printf("a2_speedflash.c (%d): Do_A2_Speedflash_WriteBlock\n", __LINE__);) + + return E_SUCCESS; +} + +ErrorCode_e A2_Speedflash_Poll(Communication_t *Communication_p) +{ + ErrorCode_e ReturValue = E_SUCCESS; + + switch (A2_SPEEDFLASH(Communication_p)->InboundState) { + case A2_SPEEDFLASH_READ_REQ: + A2_SPEEDFLASH(Communication_p)->InboundState = A2_SPEEDFLASH_WAIT_READ_REQ; + + if (E_SUCCESS != Communication_p->CommunicationDevice_p->Read((void *)A2_SPEEDFLASH(Communication_p)->Scratch, + A2_SPEEDFLASH_REQ_SIZE, A2_Speedflash_ReadCallback, Communication_p)) { + A2_SPEEDFLASH(Communication_p)->InboundState = A2_SPEEDFLASH_READ_REQ; + } + + break; + case A2_SPEEDFLASH_WAIT_READ_REQ: + /* nothing to do */ + break; + case A2_SPEEDFLASH_WRITE_BLOCK: + + if (NULL != A2_SPEEDFLASH(Communication_p)->Outbound_p) { + A2_SPEEDFLASH(Communication_p)->InboundState = A2_SPEEDFLASH_WAIT_WRITE_BLOCK; + + if (E_SUCCESS != Communication_p->CommunicationDevice_p->Write(A2_SPEEDFLASH(Communication_p)->Outbound_p, + A2_SPEEDFLASH(Communication_p)->OutboundSize, A2_Speedflash_WriteCallback, Communication_p)) { + A2_SPEEDFLASH(Communication_p)->InboundState = A2_SPEEDFLASH_WRITE_BLOCK; + } + } + + break; + case A2_SPEEDFLASH_WAIT_WRITE_BLOCK: + /* nothing to do */ + break; + } + + return ReturValue; +} + +void A2_Speedflash_WriteCallback(const void *Data_p, const uint32 Length, void *Param_p) +{ + Communication_t *Communication_p = (Communication_t *)Param_p; + + A2_SPEEDFLASH(Communication_p)->Outbound_p = NULL; + A2_SPEEDFLASH(Communication_p)->OutboundSize = 0; + + if (A2_SPEEDFLASH(Communication_p)->LastBlock) { + A2_SPEEDFLASH(Communication_p)->LastBlock = FALSE; + A2_SPEEDFLASH(Communication_p)->State = A2_SPEEDFLASH_INACTIVE; + + /* put A2 state machine in error state to reinitialize */ + A2_NETWORK(Communication_p)->Inbound.State = A2_RECEIVE_ERROR; + } else { + A2_SPEEDFLASH(Communication_p)->InboundState = A2_SPEEDFLASH_READ_REQ; + } +} + +void A2_Speedflash_ReadCallback(const void *Data_p, const uint32 Length, void *Param_p) +{ + Communication_t *Communication_p = (Communication_t *)Param_p; + A2_CommandData_t CmdData; + + CmdData.Type = A2_SPEEDFLASH_GR; + CmdData.Payload.Size = A2_SPEEDFLASH_REQ_SIZE; + CmdData.Payload.Data_p = (uint8 *)malloc(A2_SPEEDFLASH_REQ_SIZE); + + if (NULL == CmdData.Payload.Data_p) { + A_(printf("a2_speedflash.c(%d): memory allocation failed", __LINE__);) + return; + } + + A2_SPEEDFLASH(Communication_p)->InboundState = A2_SPEEDFLASH_WRITE_BLOCK; + + memcpy(CmdData.Payload.Data_p, Data_p, Length); + Communication_p->Do_CEH_Call_Fn(OBJECT_CEH_CALL(Communication_p), (CommandData_t *)&CmdData); + free(CmdData.Payload.Data_p); +} + +/** @} */ +/** @} */ +/** @} */ diff --git a/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_transport.c b/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_transport.c new file mode 100644 index 0000000..cee9aa3 --- /dev/null +++ b/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_transport.c @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + * @addtogroup a2_family + * @{ + * @addtogroup ldr_transport_layer + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include "c_system.h" +#include "r_a2_network.h" +#include "r_a2_transport.h" +#include <stdlib.h> +#include <string.h> +#include "r_basicdefinitions.h" +#include "t_time_utilities.h" +#include "r_debug.h" +#include "r_debug_macro.h" +#include "r_a2_header.h" +#include "r_a2_protocol.h" +#include "r_a2_family.h" +#include "r_a2_speedflash.h" +#include "r_communication_service.h" +#include "t_security_algorithms.h" + +/******************************************************************************* + * Declaration of file local functions + ******************************************************************************/ +static Timer_t *A2_TimerSet(A2_PacketMeta_t *Packet_p, const A2_SendData_LP_t *const InputData_p, Communication_t *Communication_p); +static void A2_Transport_OutHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p); + +/******************************************************************************* + * File scope types, constants and variables + ******************************************************************************/ + +/******************************************************************************* + * Definition of external functions + ******************************************************************************/ + +/* + * Handles all registered TL processes for A2 protocol family. + * + * @param [in] Communication_p Communication module context. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e A2_Transport_Poll(Communication_t *Communication_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; +#ifndef CFG_ENABLE_LOADER_TYPE + A2_PacketMeta_t *Packet_p = NULL; + + if (A2_SPEEDFLASH_ACTIVE == A2_SPEEDFLASH(Communication_p)->State) { + ReturnValue = A2_Speedflash_Poll(Communication_p); + VERIFY(E_SUCCESS == ReturnValue, ReturnValue); + } else { + ReturnValue = A2_Network_ReceiverHandler(Communication_p); + VERIFY(E_SUCCESS == ReturnValue, ReturnValue); + + ReturnValue = A2_Network_TransmiterHandler(Communication_p); + VERIFY(E_SUCCESS == ReturnValue, ReturnValue); + } + + Packet_p = (A2_PacketMeta_t *)QUEUE(Communication_p, FifoDequeue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p); + + if (NULL != Packet_p) { + return A2_Command_Process(Communication_p, Packet_p); + } + +#endif + +ErrorExit: + return ReturnValue; +} + +/* + * Function for sending packet in A2 protocol family. + * + * @param [in] Communication_p Communication module context. + * @param [in] InputDataIn_p Pointer to the input data. + * + * @retval E_SUCCESS After successful execution. + * @retval E_FAILED_TO_ALLOCATE_COMM_BUFFER Failed to allocate communication + * buffer. + */ +ErrorCode_e A2_Transport_Send(Communication_t *Communication_p, void *InputDataIn_p) +{ + A2_PacketMeta_t *Packet_p = NULL; + A2_SendData_LP_t *InputData_p = (A2_SendData_LP_t *)InputDataIn_p; + + Packet_p = (A2_PacketMeta_t *)A2_Network_PacketAllocate(Communication_p, A2_COMMAND_BUFFER_SIZE); + + if (NULL == Packet_p) { + A_(printf("a2_transport.c (%d): ** Failed to get available buffers! **\n", __LINE__);) + return E_FAILED_TO_ALLOCATE_COMM_BUFFER; + } + + Packet_p->Resend = 0; + Packet_p->CallBack_p = NULL; + + Packet_p->Timer_p = A2_TimerSet(Packet_p, InputData_p, Communication_p); + Packet_p->Header = *InputData_p->Header_p; + A2_SerializeHeader(Packet_p->Buffer_p, &Packet_p->Header); + + /* setup payload for calculation */ + memcpy(Packet_p->Buffer_p + A2_HEADER_LENGTH, InputData_p->Payload_p, Packet_p->Header.DataLength); + + /* Calculate Payload CRC */ + Packet_p->Communication_p = Communication_p; + + if (HASH_NONE != Communication_p->CurrentFamilyHash) { + Communication_p->HashDevice_p->Calculate(OBJECT_HASH(Communication_p), + Communication_p->CurrentFamilyHash, + (void *)Packet_p->Buffer_p, Packet_p->Header.DataLength + A2_HEADER_LENGTH, + (uint8 *)&Packet_p->CRC, (HashCallback_t)A2_Transport_OutHashCallback, + (void *)Packet_p); + } else { + memset(&Packet_p->CRC, 0x0, sizeof(uint16)); + Packet_p->Flags = Packet_p->Flags | A2_BUF_PAYLOAD_CRC_CALCULATED; + (void)QUEUE(Packet_p->Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Outbound_p, Packet_p); + } + + return E_SUCCESS; +} + +/******************************************************************************* + * Definition of internal functions + ******************************************************************************/ + +/* + * Callback function for handling calculated data. + * + * @param [in] Data_p Pointer to the data buffer for calculation. + * @param [in] Length Length of the data for calculation. + * @param [out] Hash_p Pointer to buffer with calculated hash. + * @param [in] Param_p Pointer to extra parameters. + * + * @return none. + */ +static void A2_Transport_OutHashCallback(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; + + Packet_p->Flags = Packet_p->Flags | A2_BUF_PAYLOAD_CRC_CALCULATED; + memcpy(&Packet_p->CRC, Hash_p, sizeof(uint16)); + + if (Packet_p->Header.Protocol == PROTO_A2_ACK) { + memcpy((uint8 *)((Packet_p->Buffer_p) + A2_HEADER_LENGTH_ACK), Hash_p, sizeof(uint16)); + } else { + memcpy((uint8 *)((Packet_p->Buffer_p) + A2_HEADER_LENGTH + (Packet_p->Header.DataLength)), Hash_p, sizeof(uint16)); + } + + (void)QUEUE(Packet_p->Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Outbound_p, Packet_p); +} + +/* + * Function for Timer setting. + * + * @param [in] Packet_p Pointer to the R15 packet meta data. + * @param [in] InputData_p Pointer to the input parameters with settings. + * @param [in] Communication_p Communication module context. + * + * @return none. + */ +static Timer_t *A2_TimerSet(A2_PacketMeta_t *Packet_p, const A2_SendData_LP_t *const InputData_p, Communication_t *Communication_p) +{ + Timer_t *Timer_p = NULL; + + if (InputData_p->Time > 0) { + Timer_p = (Timer_t *)malloc(sizeof(Timer_t)); + + if (NULL == Timer_p) { + return NULL; + } + + /* timer data */ + Timer_p->Time = InputData_p->Time; + Timer_p->PeriodicalTime = 0; + Timer_p->HandleFunction_p = (HandleFunction_t)(InputData_p->TimerCallBackFn_p); + Timer_p->Data_p = (void *)Packet_p; + Timer_p->Param_p = (void *)Communication_p; + } + + return Timer_p; +} +/** @} */ +/** @} */ +/** @} */ diff --git a/lcmodule/source/cnh1605204_ldr_transport_layer/source/bulk_protocol.c b/lcmodule/source/cnh1605204_ldr_transport_layer/source/bulk_protocol.c new file mode 100644 index 0000000..173bb5b --- /dev/null +++ b/lcmodule/source/cnh1605204_ldr_transport_layer/source/bulk_protocol.c @@ -0,0 +1,1461 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + * @addtogroup r15_family + * @{ + * @addtogroup bulk_protocol + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include "c_system.h" +#include "r_basicdefinitions.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "r_bulk_protocol.h" +#include "r_r15_transport_layer.h" +#include "r_r15_network_layer.h" +#include "r_r15_family.h" +#include "r_r15_header.h" +#include "r_debug.h" +#include "r_debug_macro.h" +#include "r_communication_service.h" +#include "t_security_algorithms.h" +#include "r_memmory_utils.h" + +#ifdef CFG_ENABLE_MEASUREMENT_TOOL +#include "r_measurement_tool.h" +#include "r_time_utilities.h" +#endif + +/*********************************************************************** + * Definition of external constants and variables + **********************************************************************/ +#define SESSION(x) ((R15_FamilyContext_t *)(x)->FamilyContext_p)->Transport.Session +#define CHUNKSIZE(x) ((R15_FamilyContext_t *)(x)->FamilyContext_p)->Transport.ChunkSize +#define LENGTH(x) ((R15_FamilyContext_t *)(x)->FamilyContext_p)->Transport.Length +#define OFFSET(x) ((R15_FamilyContext_t *)(x)->FamilyContext_p)->Transport.Offset +#define TOTALLENGTH(x) ((R15_FamilyContext_t *)(x)->FamilyContext_p)->Transport.BulkHandle.BulkVector_p->TotalLength +#define TRANSFEREDLENGTH(x) ((R15_FamilyContext_t *)(x)->FamilyContext_p)->Transport.BulkHandle.BulkVector_p->TransferedLength + +#ifdef CFG_ENABLE_MEASUREMENT_TOOL +extern Measurement_t *Measurement_p; +#endif + +static void R15_Bulk_ReadChunkCallBack(Communication_t *Communication_p, const void *const Timer_p, const void *const Data_p); +static void R15_Bulk_RetransmitChunks_CallBack(const Communication_t *const Communication_p, const void *const Timer_p, const void *const Data_p); +static ErrorCode_e R15_Bulk_Process_Read(Communication_t *Communication_p, TL_BulkVectorList_t *BulkVector_p, PacketMeta_t *Packet_p); +static ErrorCode_e R15_Bulk_SendReadRequest(Communication_t *Communication_p, TL_BulkVectorList_t *BulkVector_p, uint32 Chunks, void *ChunksList_p, void *CallBack_p); +static ErrorCode_e R15_Bulk_SendWriteRequest(Communication_t *Communication_p); +static void R15_Bulk_SendData(Communication_t *Communication_p, PacketMeta_t *Packet_p, uint32 ChunkId); +static boolean R15_Bulk_CheckTransmitedChunks(const TL_BulkVectorList_t *BulkVector_p); +static boolean R15_Bulk_CheckIdInList(const TL_BulkVectorList_t *BulkVector_p, const uint32 ChunkId, const uint8 *const Data_p, const uint32 Length); +static uint32 R15_Bulk_GetNextPacketChunkId(const TL_BulkVectorList_t *BulkVector_p); +static void R15_Bulk_GetListOfReceivedChunks(const TL_BulkVectorList_t *const BulkVector_p, uint32 *Chunks_p, uint8 *ChunkList_p); +static uint32 R15_Bulk_GetChunkId(const PacketMeta_t *const Packet_p); +static uint32 R15_Bulk_GetTimerChunkRetransmision(const Communication_t *const Communication_p, uint32 Time, HandleFunction_t CallBack_p); +static void R15_Bulk_MarkNotAckChunks(TL_BulkVectorList_t *BulkVector_p, const uint8 *const Payload_p, const uint32 Length); +static void R15_Bulk_MarkNotAckAllChunks(TL_BulkVectorList_t *BulkVector_p); +#ifdef CFG_ENABLE_LOADER_TYPE +static boolean R15_Bulk_CheckAcknowledgedChunks(const TL_BulkVectorList_t *BulkVector_p, const uint8 *const Payload_p); +#endif +static void R15_Bulk_OutHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p); +static TL_BulkVectorStatus_t R15_Bulk_GetVectorStatus(TL_BulkVectorList_t *BulkVector_p); +static TL_BulkSessionID_Status_t R15_Bulk_CheckBulkSession(Communication_t *Communication_p, uint16 SessionId); +static ErrorCode_e R15_Bulk_DataRequestHandler(Communication_t *Communication_p, PacketMeta_t *Packet_p); +static ErrorCode_e R15_Bulk_ReadRequestHandler(Communication_t *Communication_p, PacketMeta_t *Packet_p); + +#ifndef CFG_ENABLE_LOADER_TYPE +static void R15_Bulk_ClearBulkTmpParam(Communication_t *Communication_p); +static boolean IsChunkReceived(Communication_t *Communication_p, uint32 ChunkId); +#endif + + +/*********************************************************************** + * Definition of external functions + **********************************************************************/ +#ifndef CFG_ENABLE_LOADER_TYPE +void Do_R15_Bulk_SetCallbacks(Communication_t *Communication_p, void *BulkCommandCallback_p, void *BulkDataCallback_p, void *EndOfDump_p) +{ + R15_TRANSPORT(Communication_p)->BulkCommandCallback_p = BulkCommandCallback_p; + R15_TRANSPORT(Communication_p)->BulkDataCallback_p = BulkDataCallback_p; + R15_TRANSPORT(Communication_p)->EndOfDump_p = EndOfDump_p; +} +#endif + +/* + * Opens Bulk session. + * + * @param [in] Communication_p Communication module context. + * @param [in] SessionId Session ID. + * @param [in] Mode Type of operation(Read or Write). + * (send or receive) over the bulk protocol. + * + * @return Vector ID Vector ID of the newly opened session. + * @retval BULK_ERROR If the session can not be opened. + */ +uint32 Do_R15_Bulk_OpenSession(const Communication_t *const Communication_p, const uint16 SessionId, const TL_SessionMode_t Mode) +{ + uint32 VectorCounter; + + if (NULL == Communication_p) { + return BULK_ERROR; + } + + for (VectorCounter = 1; (VectorCounter < MAX_BULK_TL_PROCESSES) && (R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].Status != BULK_SESSION_IDLE); VectorCounter++); + + if (MAX_BULK_TL_PROCESSES != VectorCounter) { + if (R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].Status != BULK_SESSION_IDLE) { + VectorCounter = BULK_ERROR; + } else { + R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].Status = BULK_SESSION_OPEN; + R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].SessionId = SessionId; + R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].Mode = Mode; + R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].Length = 0; + R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].TransferedLength = 0; + R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].Offset = 0; + R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].ChunkSize = 0; + R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey = 0; + } + } else { + VectorCounter = BULK_ERROR; + } + + C_(printf("bulk_protocol.c (%d): Opened Bulk session(%d)with VId(%d)\n", __LINE__, SessionId, VectorCounter);) + return VectorCounter; +} + +/* + * Creates Bulk Vector. + * + * @param [in] Communication_p Communication module context. + * @param [in] BulkVector Index of Bulk Vector. + * @param [in] Length Data Length in bytes. + * @param [in] BuffSize Requested size of each Buffer. + * @param [in] CreatedBulkVector_p Already created bulk vector which + * need to be updated with correct + * information. + * + * @return Vector ID The ID of the Vector that has been created. + * @retval BULK_ERROR If creation of vector failed. + */ +TL_BulkVectorList_t *Do_R15_Bulk_CreateVector(const Communication_t *const Communication_p, const uint32 BulkVector, uint32 Length, const uint32 BuffSize, TL_BulkVectorList_t *CreatedBulkVector_p) +{ + uint32 Counter; + uint32 AvailableBuffers = 0; + uint32 Buffers; + PacketMeta_t *Packet_p = NULL; + TL_BulkVectorList_t *BulkVector_p = NULL; + + if (NULL == Communication_p) { + return NULL; + } + +#ifndef CFG_ENABLE_LOADER_TYPE + int BuffersNr = 0; +#endif + + /* check input parameters */ + if ((0 == BulkVector) || (MAX_BULK_TL_PROCESSES <= BulkVector) || (BuffSize == 0) || (BuffSize > (BULK_BUFFER_SIZE - ALIGNED_HEADER_LENGTH - ALIGNED_BULK_EXTENDED_HEADER_LENGTH)) || (Length == 0)) { + A_(printf("bulk_protocol.c (%d): ** Invalid input parameters! **\n", __LINE__);) + return NULL; + } + + BulkVector_p = &(R15_TRANSPORT(Communication_p)->BulkVectorList[BulkVector]); + + if (NULL == CreatedBulkVector_p) { + Buffers = ((Length + BuffSize - 1) / BuffSize); + + if (0 == Buffers) { + return NULL; + } + + AvailableBuffers = BUFFER(Communication_p, BuffersAvailable_Fn)(OBJECT_BUFFER(Communication_p), BULK_BUFFER_SIZE); + + if (AvailableBuffers >= Buffers) { + BulkVector_p->Length = Length; + BulkVector_p->Buffers = Buffers; + BulkVector_p->ChunkSize = BuffSize; + BulkVector_p->Offset = 0; + + for (Counter = 0; (Counter < Buffers); Counter++) { + BulkVector_p->Entries[Counter].Buffer_p = NULL; + + if (BULK_SEND == BulkVector_p->Mode) { +#ifdef CFG_ENABLE_LOADER_TYPE + Packet_p = R15_Network_PacketAllocate(Communication_p, BULK_BUFFER_SIZE); + + if (NULL == Packet_p) { + A_(printf("bulk_protocol.c (%d): ** Memory allocation failed! **\n", __LINE__);) + return NULL; + } + + Packet_p->ExtendedHeader_p = Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER + ALIGNED_HEADER_LENGTH; + Packet_p->Payload_p = Packet_p->ExtendedHeader_p + ALIGNED_BULK_EXTENDED_HEADER_LENGTH; +#else + /* packet meta info allocate */ + Packet_p = (PacketMeta_t *)malloc(sizeof(PacketMeta_t)); + + if (NULL == Packet_p) { + return NULL; + } + + memset(Packet_p, 0, sizeof(PacketMeta_t)); + + /* packet meta info setup */ + Packet_p->Buffer_p = NULL; + Packet_p->BufferSize = BULK_BUFFER_SIZE; + SET_PACKET_FLAGS(Packet_p, PACKET_ALLOCATION_STATE_MASK, BUF_ALLOCATED); + Packet_p->Payload_p = (uint8 *)(HEADER_OFFSET_IN_BUFFER + ALIGNED_HEADER_LENGTH + ALIGNED_BULK_EXTENDED_HEADER_LENGTH); + Packet_p->ExtendedHeader_p = Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER + ALIGNED_HEADER_LENGTH; + BuffersNr = 0; + + do { + if (NULL == R15_NETWORK(Communication_p)->MetaInfoList[BuffersNr]) { + R15_NETWORK(Communication_p)->MetaInfoList[BuffersNr] = Packet_p; + break; + } + + BuffersNr ++; + } while (BuffersNr < (COMMAND_BUFFER_COUNT + BULK_BUFFER_COUNT)); + + if (COMMAND_BUFFER_COUNT + BULK_BUFFER_COUNT <= BuffersNr) { + BUFFER_FREE(Packet_p); + return NULL; + } + +#endif // #ifdef CFG_ENABLE_LOADER_TYPE + + BulkVector_p->Entries[Counter].Buffer_p = Packet_p; + BulkVector_p->Entries[Counter].Payload_p = Packet_p->Payload_p; + BulkVector_p->Entries[Counter].Hash_p = Packet_p->Hash; + } + } + } else { + A_(printf("bulk_protocol.c (%d) ** Not enough buffers! ** \n", __LINE__);) + return NULL; + } + } else { + memcpy(BulkVector_p, CreatedBulkVector_p, sizeof(TL_BulkVectorList_t)); + } + + return BulkVector_p; +} + +/* + * Frees Bulk Vector. + * + * @param [in] Communication_p Communication module context. + * @param [in] BulkVector_p Pointer to the Bulk Vector. + * @param [in] ReqReleaseBuffer Defines if complete buffers with metadata will + * be released or only only the metadata will be cleared. + * + * @retval E_SUCCESS After successful execution. + * @retval BULK_ERROR Error while destroying vector. + */ +uint32 Do_R15_Bulk_DestroyVector(const Communication_t *const Communication_p, TL_BulkVectorList_t *BulkVector_p, boolean ReqReleaseBuffer) +{ + uint32 ReturnValue = E_SUCCESS; + uint32 Counter; + int BuffersNr = 0; + + if (NULL == Communication_p) { + return BULK_ERROR; + } + + if (NULL == BulkVector_p) { + A_(printf("bulk_protocol.c (%d): ** Invalid bulk vector! **\n", __LINE__);) + return BULK_ERROR; + } + + for (Counter = 0; (Counter < BulkVector_p->Buffers); Counter++) { + /* clear all flags by setting buffer as free */ + BulkVector_p->Entries[Counter].Buffer_p->Flags = BUF_FREE; + BulkVector_p->Entries[Counter].Hash_p = NULL; + + if (NULL != BulkVector_p->Entries[Counter].Buffer_p) { + if (ReqReleaseBuffer) { + ReturnValue = R15_Network_PacketRelease(Communication_p, BulkVector_p->Entries[Counter].Buffer_p); + BulkVector_p->Entries[Counter].Buffer_p = NULL; + } else { + C_(printf("bulk_protocol.c (%d): Destroyed meta info data (0x%x)for bulk buffers! \n", __LINE__, BulkVector_p->Entries[Counter].Buffer_p);) + BuffersNr = 0; + + do { + if (BulkVector_p->Entries[Counter].Buffer_p == R15_NETWORK(Communication_p)->MetaInfoList[BuffersNr]) { + R15_NETWORK(Communication_p)->MetaInfoList[BuffersNr] = NULL; + /* release meta info for buffer */ + free(BulkVector_p->Entries[Counter].Buffer_p); + BulkVector_p->Entries[Counter].Buffer_p = NULL; + break; + } + + BuffersNr ++; + } while (BuffersNr < (COMMAND_BUFFER_COUNT + BULK_BUFFER_COUNT)); + } + } + } + + C_(printf("bulk_protocol.c (%d): Destroyed bulk vector for session(%d)! \n", __LINE__, BulkVector_p->SessionId);) + BulkVector_p->Status = BULK_SESSION_IDLE; + BulkVector_p->SessionId = 0; + BulkVector_p->Mode = BULK_RECEIVE; + BulkVector_p->Length = 0; + BulkVector_p->Buffers = 0; + BulkVector_p->ChunkSize = 0; + BulkVector_p->Offset = 0; + + return ReturnValue; +} + +/* + * Start specified bulk session. + * + * @param [in] Communication_p Communication module context. + * @param [in] BulkVector_p Pointer to the Bulk Vector. + * @param [in] Offset Sets the offset from where data + * read/write should be performed. + * + * @retval E_INVALID_BULK_MODE Invalid bulk mode. + * @retval E_FAILED_TO_START_BULK_SESSION Either the session is + * invalid or the BulkVector is invalid. + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e Do_R15_Bulk_StartSession(Communication_t *Communication_p, TL_BulkVectorList_t *BulkVector_p, const uint64 Offset) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + uint32 ChunkId; + + VERIFY(NULL != Communication_p, E_INVALID_INPUT_PARAMETERS); + + /* Verify the new bulk vector. */ + VERIFY(NULL != BulkVector_p, E_INVALID_INPUT_PARAMETERS); + /* Verify that the bulk session is opend for this bulk vector. */ + VERIFY(BULK_SESSION_IDLE != BulkVector_p->Status, E_FAILED_TO_START_BULK_SESSION); + /* Verify that the previouse bulk session is closed. */ + VERIFY(NULL == R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p, E_PREVIOUS_BULK_SESSION_IS_NOT_CLOSED); + + BulkVector_p->Status = BULK_SESSION_PROCESSING; + BulkVector_p->Offset = Offset; + + /* set the handle for the current bulk vector */ + R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p = BulkVector_p; + R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey = 0; + + C_(printf("bulk_protocol.c(%d) Session(%d) Started!\n", __LINE__, BulkVector_p->SessionId);) + C_(printf("bulk_protocol.c(%d) Req: Chunks(%d) ChunkSize(%d) Length(%d)\n", __LINE__, BulkVector_p->Buffers, BulkVector_p->ChunkSize, BulkVector_p->Length);) + + if (BULK_RECEIVE == BulkVector_p->Mode) { + /* Set BULK READ state machine */ +#ifdef CFG_ENABLE_LOADER_TYPE + BulkVector_p->State = SEND_READ_REQUEST; +#else + BulkVector_p->State = WAIT_WRITE_REQUEST; +#endif + ReturnValue = R15_Bulk_Process_Read(Communication_p, BulkVector_p, NULL); + } else { + VERIFY(BULK_SEND == BulkVector_p->Mode, E_INVALID_BULK_MODE); + + for (ChunkId = 0; ChunkId < BulkVector_p->Buffers; ChunkId++) { + SET_PACKET_FLAGS(BulkVector_p->Entries[ChunkId].Buffer_p, PACKET_TX_STATE_MASK, BUF_TX_READY); + } + + /* Set BULK WRITE state machine */ +#ifdef CFG_ENABLE_LOADER_TYPE + BulkVector_p->State = SEND_WRITE_REQUEST; +#else + BulkVector_p->State = WAIT_READ_REQUEST; +#endif + ReturnValue = R15_Bulk_Process_Write(Communication_p, BulkVector_p); + } + +#ifdef CFG_ENABLE_MEASUREMENT_TOOL + ReturnValue = Do_Measurement_CreateSessionMeasurementData(Communication_p, &(Measurement_p->MeasurementData_p->SessionMeasurement_p), + NULL, BulkVector_p->Buffers, BulkVector_p->SessionId); + ReturnValue = MP(Measurement_p, 0, START_SESSION_TIME); +#endif +ErrorExit: + return ReturnValue; +} + + +/* + * Get status of bulk transfer. + * + * @param [in] BulkVector_p Pointer to the Bulk Vector. + * + * @retval BULK_SESSION_IDLE Idle state of bulk protocol. + * @retval BULK_SESSION_OPEN Opened bulk protocol and ready for + * transmitting. + * @retval BULK_SESSION_PROCESSING Processing bulk transfer. + * @retval BULK_SESSION_FINISHED Bulk transfer finished. + */ +TL_BulkSessionState_t Do_R15_Bulk_GetStatusSession(const TL_BulkVectorList_t *BulkVector_p) +{ + if (NULL != BulkVector_p) { + return BulkVector_p->Status; + } + + return BULK_SESSION_IDLE; +} + +/* + * Close specified Bulk session. + * + * @param [in] Communication_p Communication module context. + * @param [in] BulkVector_p Pointer to the Bulk Vector. + * for the session you want to close. + * + * @retval E_SUCCESS After successful execution. + * @retval E_FAILED_TO_CLOSE_BULK_SESSION If the BulkVector is not valid. + */ +//lint -e{818} +ErrorCode_e Do_R15_Bulk_CloseSession(Communication_t *Communication_p, TL_BulkVectorList_t *BulkVector_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + + VERIFY(NULL != Communication_p, E_INVALID_INPUT_PARAMETERS); + + /* Verify that the requested bulk session is started. */ + VERIFY(NULL != BulkVector_p, E_FAILED_TO_CLOSE_BULK_SESSION); + + R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p = NULL; + + C_(printf("bulk_protocol.c (%d): Bulk session(%d) closed! \n", __LINE__, BulkVector_p->SessionId);) +#ifdef CFG_ENABLE_MEASUREMENT_TOOL + ReturnValue = MP(Measurement_p, 0, END_SESSION_TIME); +#endif + +ErrorExit: + return ReturnValue; +} + + +/* + * Handling received bulk command. + * + * @param [in] Communication_p Communication module context. + * @param [in] Packet_p Pointer to the received buffer. + * + * @retval E_SUCCESS After successful execution. + * @retval E_INVALID_INPUT_PARAMETERS If Packet_p is NULL. + */ +ErrorCode_e R15_Bulk_Process(Communication_t *Communication_p, PacketMeta_t *Packet_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + BulkExtendedHeader_t ExtendedHeader = {0}; +#ifdef CFG_ENABLE_LOADER_TYPE + TL_BulkVectorList_t *BulkVector_p = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p; + TL_BulkVectorList_t *PreviousBulkVector_p = &(R15_TRANSPORT(Communication_p)->PreviousBulkVector); + uint32 ChunksCount = 0; + uint8 ChunksList[MAX_BULK_TL_PROCESSES]; +#endif + + /* check input parameters */ + VERIFY(NULL != Packet_p, E_INVALID_INPUT_PARAMETERS); + + //lint --e(826) + R15_DeserializeBulkExtendedHeader(&ExtendedHeader, Packet_p->ExtendedHeader_p); + VERIFY(ExtendedHeader.Session > 0, E_INVALID_BULK_SESSION_ID); + + /* check bulk session opened? */ +#ifdef CFG_ENABLE_LOADER_TYPE + + if ((NULL == BulkVector_p) || (ExtendedHeader.Session != BulkVector_p->SessionId)) { + C_(printf("bulk_protocol.c (%d): Session is not opend(%d) or wrong session(%d)! \n", __LINE__, R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p, ExtendedHeader.Session);) + + if ((CMD_BULK_DATA == (ExtendedHeader.TypeFlags & MASK_BULK_COMMAND_SELECT)) && + NULL != PreviousBulkVector_p) { + // make the list of received chunks + R15_Bulk_GetListOfReceivedChunks(PreviousBulkVector_p, &ChunksCount, ChunksList); + // send read ACK for previous session + ReturnValue = R15_Bulk_SendReadRequest(Communication_p, PreviousBulkVector_p, ChunksCount, ChunksList, NULL); + } + + // release the buffer used for the invalid packet + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + goto ErrorExit; + } + +#endif + + switch (ExtendedHeader.TypeFlags & MASK_BULK_COMMAND_SELECT) { + case CMD_BULK_DATA: + ReturnValue = R15_Bulk_DataRequestHandler(Communication_p, Packet_p); + break; + + case CMD_BULK_READ: + ReturnValue = R15_Bulk_ReadRequestHandler(Communication_p, Packet_p); + break; + +#ifndef CFG_ENABLE_LOADER_TYPE + case CMD_BULK_WRITE: + + if (NULL != R15_TRANSPORT(Communication_p)->BulkCommandCallback_p) { + BulkCommandReqCallback_t pcbf; + SESSION(Communication_p) = ExtendedHeader.Session; + CHUNKSIZE(Communication_p) = ExtendedHeader.ChunkSize; + OFFSET(Communication_p) = ExtendedHeader.Offset; + LENGTH(Communication_p) = ExtendedHeader.Length; + pcbf = (BulkCommandReqCallback_t)R15_TRANSPORT(Communication_p)->BulkCommandCallback_p; + pcbf(Communication_p->Object_p, &SESSION(Communication_p), &CHUNKSIZE(Communication_p), &OFFSET(Communication_p), &LENGTH(Communication_p), FALSE); + R15_Bulk_ClearBulkTmpParam(Communication_p); + } + + /* release the buffer for undefined command */ + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + break; +#endif + case CMD_BULK_STATUS: + // not implemented. + A_(printf("bulk_protocol.c (%d): ** Not implemented bulk command! **\n", __LINE__);) + /* release the buffer for unimplemented command */ + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + break; + + default: + A_(printf("bulk_protocol.c (%d): ** Undefined bulk command! **\n", __LINE__);) + /* release the buffer for undefined command */ + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + break; + } + +ErrorExit: + return ReturnValue; +} + + +#ifdef CFG_ENABLE_LOADER_TYPE +/* + * Generate bulk Session ID. Allowed bulk session ID is from 1 to 65535. + * + * @param [in] Communication_p Communication module context. + * + * @retval Session ID Next free session ID. + */ +uint16 Do_R15_Bulk_GenerateBulkSessionID(Communication_t *Communication_p) +{ + if (NULL == Communication_p) { + return 0; + } + + R15_TRANSPORT(Communication_p)->BulkSessionCounter++; + + if (R15_TRANSPORT(Communication_p)->BulkSessionCounter == 0) { + R15_TRANSPORT(Communication_p)->BulkSessionCounter = 1; + } + + return R15_TRANSPORT(Communication_p)->BulkSessionCounter; +} +#endif + +/*********************************************************************** + * Definition of internal functions + **********************************************************************/ + +/* + * Get the Chunk ID for the next bulk packet which is ready for transmitting. + * + * @param [in] BulkVector_p Current bulk vector used for bulk transfer. + * + * @retval ChunkID Chunk ID for the next ready for transmitting packet. + * If none chunk is ready return last Chunk ID + 1. + */ +static uint32 R15_Bulk_GetNextPacketChunkId(const TL_BulkVectorList_t *BulkVector_p) +{ + uint32 ChunkId = 0; + + for (ChunkId = 0; ChunkId < BulkVector_p->Buffers; ChunkId++) { + if (CHECK_PACKET_FLAGS(BulkVector_p->Entries[ChunkId].Buffer_p, BUF_TX_READY)) { + break; + } + } + + return ChunkId; +} + +/* + * Check all created chunks is it transmited. + * + * @param [in] BulkVector_p Current bulk vector used for bulk transfer. + * @param [in] ChunkId ChunkID for the packet which need to be transmitted. + * + * @retval TRUE If all created chunks are transmitted. + * @retval FALSE If all created chunks are not transmitted. + */ +static boolean R15_Bulk_CheckTransmitedChunks(const TL_BulkVectorList_t *BulkVector_p) +{ + uint32 ChunkId; + + for (ChunkId = 0; ChunkId < BulkVector_p->Buffers; ChunkId++) { + if (!CHECK_PACKET_FLAGS(BulkVector_p->Entries[ChunkId].Buffer_p, BUF_TX_SENT)) { + return FALSE; + } + } + + return TRUE; +} + +#ifdef CFG_ENABLE_LOADER_TYPE +/* + * Check all acknowledged chunks. + * + * @param [in] BulkVector_p Current bulk vector used for bulk transfer. + * @param [in] Payload_p List of the acknowledged chunks. + * + * @retval TRUE If all transmitted chunks are acknowledged. + * @retval FALSE If all transmitted chunks are not acknowledged. + */ +static boolean R15_Bulk_CheckAcknowledgedChunks(const TL_BulkVectorList_t *BulkVector_p, const uint8 *const Payload_p) +{ + uint32 i; + uint8 Data[16]; + + memset(Data, 0, 16); + + for (i = 0; i < BulkVector_p->Buffers; i++) { + Data[i] = (uint8)i; + } + + if (memcmp(Data, Payload_p, BulkVector_p->Buffers) == 0) { + return TRUE; + } + + return FALSE; +} +#endif + +static void R15_Bulk_MarkNotAckChunks(TL_BulkVectorList_t *BulkVector_p, const uint8 *const Payload_p, const uint32 Length) +{ + uint32 ChunkId; + + for (ChunkId = 0; ChunkId < BulkVector_p->Buffers; ChunkId++) { + if (!R15_Bulk_CheckIdInList(BulkVector_p, ChunkId, Payload_p, Length) && + !CHECK_PACKET_FLAGS(BulkVector_p->Entries[ChunkId].Buffer_p, BUF_TX_SENDING)) { + SET_PACKET_FLAGS(BulkVector_p->Entries[ChunkId].Buffer_p, PACKET_TX_STATE_MASK, BUF_TX_READY); + BulkVector_p->State = SENDING_CHUNKS; + } + } +} + +static void R15_Bulk_MarkNotAckAllChunks(TL_BulkVectorList_t *BulkVector_p) +{ + uint32 ChunkId; + + for (ChunkId = 0; ChunkId < BulkVector_p->Buffers; ChunkId++) { + SET_PACKET_FLAGS(BulkVector_p->Entries[ChunkId].Buffer_p, PACKET_TX_STATE_MASK, BUF_TX_READY); + } + + BulkVector_p->State = SENDING_CHUNKS; +} + +static boolean R15_Bulk_CheckIdInList(const TL_BulkVectorList_t *BulkVector_p, const uint32 ChunkId, const uint8 *const Data_p, const uint32 Length) +{ + uint32 i; + + for (i = 0; i < Length; i++) { + if (ChunkId == *(Data_p + i)) { + return TRUE; + } + } + + return FALSE; +} + +static ErrorCode_e R15_Bulk_Process_Read(Communication_t *Communication_p, TL_BulkVectorList_t *BulkVector_p, PacketMeta_t *Packet_p) +{ + uint32 ChunkId = 0; + uint8 ChunksList[MAX_BULK_TL_PROCESSES]; + ErrorCode_e ReturnValue = E_SUCCESS; + TL_BulkVectorStatus_t ChunkReceivedStatus; +#ifndef CFG_ENABLE_LOADER_TYPE + BulkCommandReqCallback_t pcbf; +#endif + + if (NULL == BulkVector_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + switch (BulkVector_p->State) { + /* Idle state */ + case BULK_IDLE_STATE: + // wait to start the bulk session + break; + +#ifndef CFG_ENABLE_LOADER_TYPE + /* coverity[unterminated_case] */ + case WAIT_WRITE_REQUEST: + BulkVector_p->State = SEND_READ_REQUEST; +#endif //CFG_ENABLE_LOADER_TYPE + + /* coverity[fallthrough] */ + case SEND_READ_REQUEST: + //lint --e(611) + ReturnValue = R15_Bulk_SendReadRequest(Communication_p, BulkVector_p, 0, NULL, (void *)R15_Bulk_ReadChunkCallBack); + + if (E_SUCCESS == ReturnValue) { + BulkVector_p->State = WAIT_CHUNKS; + } + + break; + + case WAIT_CHUNKS: + ChunkId = R15_Bulk_GetChunkId(Packet_p); + + /* Try to release the timer for the bulk read request */ + if (R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey > 0) { + (void)TIMER(Communication_p, TimerRelease_Fn)(OBJECT_TIMER(Communication_p), R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey); + R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey = 0; + } + + C_(printf("bulk_protocol.c(%d) Received Chunk(%d) Size(%d) Length(%d)\n", __LINE__, ChunkId, ((BulkExtendedHeader_t *)(Packet_p->ExtendedHeader_p))->ChunkSize, ((BulkExtendedHeader_t *)(Packet_p->ExtendedHeader_p))->Length);) + +#ifdef CFG_ENABLE_MEASUREMENT_TOOL + ReturnValue = MP(Measurement_p, ChunkId, RECEIVED_CHUNK_TIME); +#endif + + if (ChunkId >= BulkVector_p->Buffers) { + /* Packet with invalid chunk Id and release the buffer. */ + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + break; + } else if (NULL == BulkVector_p->Entries[ChunkId].Buffer_p) { + BulkVector_p->Entries[ChunkId].Buffer_p = Packet_p; + + SET_PACKET_FLAGS(BulkVector_p->Entries[ChunkId].Buffer_p, PACKET_RX_STATE_MASK, BUF_ACK_READY); + //lint --e(413) + BulkVector_p->Entries[ChunkId].Payload_p = Packet_p->Payload_p; + //lint --e(413) + BulkVector_p->Entries[ChunkId].Hash_p = Packet_p->Hash; + + /* */ + C_(printf("bulk_protocol.c(%d) Received Chunks until (%d)\n", __LINE__, ChunkId);) + } else { + /* Packet with already received chunk Id. Release the network packet. */ + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + } + + /* make the list of received chunks and send for retransmission of all missed chunks */ + R15_Bulk_GetListOfReceivedChunks(BulkVector_p, &ChunkId, ChunksList); + + /* check if all chunks are received */ + ChunkReceivedStatus = R15_Bulk_GetVectorStatus(BulkVector_p); + + if (VECTOR_COMPLETE == ChunkReceivedStatus) { + C_(printf("bulk_protocol.c(%d) Last Chunk Received (%d)\n", __LINE__, ChunkId);) + /* save the current bulk vector before is bulk session closed */ + memcpy(&(R15_TRANSPORT(Communication_p))->PreviousBulkVector, BulkVector_p, sizeof(TL_BulkVectorList_t)); + ReturnValue = R15_Bulk_SendReadRequest(Communication_p, BulkVector_p, ChunkId, ChunksList, NULL); + BulkVector_p->Status = BULK_SESSION_FINISHED; + BulkVector_p->State = BULK_IDLE_STATE; +#ifndef CFG_ENABLE_LOADER_TYPE + // notify session end + pcbf = (BulkCommandReqCallback_t)R15_TRANSPORT(Communication_p)->BulkCommandCallback_p; + pcbf(Communication_p->Object_p, &BulkVector_p->SessionId, &BulkVector_p->ChunkSize, &BulkVector_p->Offset, &BulkVector_p->Length, TRUE); +#endif + } else if (VECTOR_MISSING_CHUNK == ChunkReceivedStatus) { + ReturnValue = R15_Bulk_SendReadRequest(Communication_p, BulkVector_p, ChunkId, ChunksList, NULL); + } else { // Chunks are received in order + R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey = R15_Bulk_GetTimerChunkRetransmision(Communication_p, R15_TIMEOUTS(Communication_p)->TBDR, (HandleFunction_t)R15_Bulk_ReadChunkCallBack); + } + + break; + + case SEND_BULK_ACK: //TODO: check this state. look like unused state!!! + R15_Bulk_GetListOfReceivedChunks(BulkVector_p, &ChunkId, ChunksList); + ReturnValue = R15_Bulk_SendReadRequest(Communication_p, BulkVector_p, ChunkId, ChunksList, NULL); + break; + + default: + BulkVector_p->State = BULK_IDLE_STATE; + ReturnValue = E_INVALID_BULK_PROTOCOL_STATE; + break; + } + + return ReturnValue; +} + + +/* + * State machine for bulk transfer from ME to PC. + * + * @param [in] Communication_p Communication module context. + * @param [in] BulkVector_p Pointer to the received buffer. + * + */ +ErrorCode_e R15_Bulk_Process_Write(Communication_t *Communication_p, TL_BulkVectorList_t *BulkVector_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + uint32 ChunkId; + static uint32 reentrant = 1; + + if (reentrant) { + reentrant = 0; + + if (BulkVector_p->Mode == BULK_SEND) { + switch (BulkVector_p->State) { + /* Idle state */ + case BULK_IDLE_STATE: + // wait to start the bulk session + break; + + case SEND_WRITE_REQUEST: + ReturnValue = R15_Bulk_SendWriteRequest(Communication_p); + + if (E_SUCCESS == ReturnValue) { + BulkVector_p->State = WAIT_READ_REQUEST; + } + + break; + + case WAIT_BULK_ACK: + //...? + break; + + case WAIT_READ_REQUEST: +#ifndef CFG_ENABLE_LOADER_TYPE + //TODO find end release timer for retransmision + BulkVector_p->State = SENDING_CHUNKS; +#else + //... + break; +#endif + + /* continue to send chunks */ + case SENDING_CHUNKS: + /* get Chunk ID of next packet! */ + ChunkId = R15_Bulk_GetNextPacketChunkId(BulkVector_p); + + if (ChunkId <= BulkVector_p->Buffers - 1) { + /* get and send packet with chunk ID */ + R15_Bulk_SendData(Communication_p, BulkVector_p->Entries[ChunkId].Buffer_p, ChunkId); +#ifndef CFG_ENABLE_LOADER_TYPE + + if (NULL != R15_TRANSPORT(Communication_p)->BulkDataCallback_p) { + BulkDataReqCallback_t pcbf; + SESSION(Communication_p) = BulkVector_p->SessionId; + CHUNKSIZE(Communication_p) = BulkVector_p->ChunkSize; + OFFSET(Communication_p) = BulkVector_p->Offset; + LENGTH(Communication_p) = BulkVector_p->Length; + TRANSFEREDLENGTH(Communication_p) += CHUNKSIZE(Communication_p); + pcbf = (BulkDataReqCallback_t)R15_TRANSPORT(Communication_p)->BulkDataCallback_p; + pcbf(Communication_p->Object_p, &SESSION(Communication_p), &CHUNKSIZE(Communication_p), &OFFSET(Communication_p), &LENGTH(Communication_p), &TOTALLENGTH(Communication_p), &TRANSFEREDLENGTH(Communication_p)); + } + +#endif + C_(printf("bulk_protocol.c(%d) Sent chunk (%d) session (%d)\n", __LINE__, ChunkId, BulkVector_p->SessionId);) + } else { + /* all chunks are in process of sending, wait for chunks to be sent */ + if (R15_Bulk_CheckTransmitedChunks(BulkVector_p)) { + /* save the current bulk vector before bulk session is closed */ + memcpy(&(R15_TRANSPORT(Communication_p))->PreviousBulkVector, BulkVector_p, sizeof(TL_BulkVectorList_t)); + R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey = R15_Bulk_GetTimerChunkRetransmision(Communication_p, R15_TIMEOUTS(Communication_p)->TBCR, (HandleFunction_t)R15_Bulk_RetransmitChunks_CallBack); + BulkVector_p->State = WAIT_BULK_ACK; + C_(printf("bulk_protocol.c(%d) Wait BULK ACK for session (%d)!\n", __LINE__, BulkVector_p->SessionId);) + } + } + +#ifdef CFG_ENABLE_MEASUREMENT_TOOL + ReturnValue = MP(Measurement_p, ChunkId, RECEIVED_CHUNK_TIME); +#endif + break; + + case WRITE_BULK_FINISH: + BulkVector_p->State = BULK_IDLE_STATE; + BulkVector_p->Status = BULK_SESSION_FINISHED; + C_(printf("bulk_protocol.c(%d) Write bulk process finished! \n", __LINE__);) + break; + + default: + BulkVector_p->State = BULK_IDLE_STATE; + break; + } + } + + reentrant = 1; + } + + return ReturnValue; +} + + +static ErrorCode_e R15_Bulk_SendReadRequest(Communication_t *Communication_p, TL_BulkVectorList_t *BulkVector_p, uint32 Chunks, void *ChunksList_p, void *CallBack_p) +{ + ErrorCode_e ReturnValue = E_GENERAL_COMMUNICATION_ERROR; + BulkExtendedHeader_t ExtendedHeader; + R15_Header_t Header; + SendData_LP_t Param; + + /* setup header data */ + Header.Protocol = BULK_PROTOCOL; + Header.Flags = Communication_p->CurrentFamilyHash; + Header.PayloadLength = Chunks * sizeof(uint8); + Header.PayloadChecksum = 0; + Header.ExtendedHeaderLength = BULK_EXTENDED_HEADER_LENGTH; + Header.ExtendedHeaderChecksum = 0; + + /* Set extended header parameters */ + ExtendedHeader.Session = BulkVector_p->SessionId; + ExtendedHeader.AcksChunk = (uint8)Chunks; + ExtendedHeader.ChunkSize = BulkVector_p->ChunkSize; + ExtendedHeader.Offset = BulkVector_p->Offset; + ExtendedHeader.Length = BulkVector_p->Length; + ExtendedHeader.TypeFlags = CMD_BULK_READ; + + Param.Header_p = &Header; + Param.ExtendedHeader_p = &ExtendedHeader; + + //TODO: (xvlapis) check if ChunksList_p=NULL meaning ReadCMD which requires retransmission timer, else ReadACK CMD which doesn't require retransmission + if (0 != Chunks) { + VERIFY(NULL != ChunksList_p, E_INVALID_INPUT_PARAMETERS); + Param.Payload_p = ChunksList_p; + Param.TimerCallBackFn_p = NULL; + Param.Time = 0; + } else { + Param.Time = R15_TIMEOUTS(Communication_p)->TBDR; // Receiving chunks + + if (Chunks != 0) { + VERIFY(NULL != ChunksList_p, E_INVALID_INPUT_PARAMETERS); + Param.Payload_p = ChunksList_p; + } + + VERIFY(NULL != CallBack_p, E_INVALID_INPUT_PARAMETERS); + //lint --e(611) + Param.TimerCallBackFn_p = (HandleFunction_t)CallBack_p; + } + + ReturnValue = R15_Transport_Send(Communication_p, &Param); + +ErrorExit: + return ReturnValue; +} + + +static ErrorCode_e R15_Bulk_SendWriteRequest(Communication_t *Communication_p) +{ + ErrorCode_e ReturnValue = E_GENERAL_COMMUNICATION_ERROR; + BulkExtendedHeader_t ExtendedHeader; + R15_Header_t Header; + SendData_LP_t Param; + TL_BulkVectorList_t *BulkVector_p = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p; + + /* setup header data */ + Header.Protocol = BULK_PROTOCOL; + Header.Flags = Communication_p->CurrentFamilyHash; + Header.PayloadLength = 0; + Header.PayloadChecksum = 0; + Header.ExtendedHeaderLength = BULK_EXTENDED_HEADER_LENGTH; + Header.ExtendedHeaderChecksum = 0; + + /* Set extended header parameters */ + ExtendedHeader.Session = BulkVector_p->SessionId; + ExtendedHeader.AcksChunk = 0; + ExtendedHeader.ChunkSize = BulkVector_p->ChunkSize; + ExtendedHeader.Offset = BulkVector_p->Offset; + ExtendedHeader.Length = BulkVector_p->Length; + ExtendedHeader.TypeFlags = CMD_BULK_WRITE; + + Param.Header_p = &Header; + Param.ExtendedHeader_p = &ExtendedHeader; + Param.Payload_p = NULL; + Param.Time = R15_TIMEOUTS(Communication_p)->TBCR; + Param.TimerCallBackFn_p = NULL; + ReturnValue = R15_Transport_Send(Communication_p, &Param); + return ReturnValue; +} + + +static void R15_Bulk_SendData(Communication_t *Communication_p, PacketMeta_t *Packet_p, uint32 ChunkId) +{ + BulkExtendedHeader_t ExtendedHeader; + R15_Header_t Header; + TL_BulkVectorList_t *BulkVector_p = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p; + uint32 DeltaLength = 0; + + /* check if packet is already serialized and calculated */ + if (!CHECK_PACKET_FLAGS(Packet_p, (BUF_ALLOCATED | BUF_TX_READY | BUF_PAYLOAD_CRC_CALCULATED))) { + Packet_p->Timer_p = NULL; + Packet_p->Resend = 0; + /* set call back function */ + Packet_p->CallBack_p = NULL; + + /* setup header data */ + memset(&Header, 0, HEADER_LENGTH); + Header.Protocol = BULK_PROTOCOL; + Header.Flags = Communication_p->CurrentFamilyHash; + + if ((ChunkId + 1) == BulkVector_p->Buffers) { + DeltaLength = (ChunkId + 1) * BulkVector_p->ChunkSize - BulkVector_p->Length; + + if (DeltaLength == 0) { + Header.PayloadLength = BulkVector_p->ChunkSize; + } else { + Header.PayloadLength = BulkVector_p->ChunkSize - DeltaLength; + } + } else { + Header.PayloadLength = BulkVector_p->ChunkSize; + } + + Header.ExtendedHeaderLength = BULK_EXTENDED_HEADER_LENGTH; + + /* Set extended header parameters */ + ExtendedHeader.Session = BulkVector_p->SessionId; + ExtendedHeader.AcksChunk = (uint8)ChunkId; + ExtendedHeader.ChunkSize = BulkVector_p->ChunkSize; + ExtendedHeader.Offset = BulkVector_p->Offset; + ExtendedHeader.Length = BulkVector_p->Length; + ExtendedHeader.TypeFlags = CMD_BULK_DATA; + + /* serialize and calculate extended header */ + Packet_p->ExtendedHeader_p = Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER + ALIGNED_HEADER_LENGTH; + R15_SerializeExtendedHeader(Packet_p->ExtendedHeader_p, Header.Protocol, &ExtendedHeader, &(Header.ExtendedHeaderChecksum)); + /* setup header for serialization and calculation */ + memcpy(&Packet_p->Header, &Header, HEADER_LENGTH); + + /* Calculate Payload CRC */ + Packet_p->Communication_p = Communication_p; + SET_PACKET_FLAGS(Packet_p, PACKET_CRC_STATE_MASK, BUF_CRC_CALCULATING); + + if (HASH_NONE != Packet_p->Header.Flags) { + Communication_p->HashDevice_p->Calculate(OBJECT_HASH(Communication_p), + (HashType_e)Packet_p->Header.Flags, + (void *)Packet_p->Payload_p, Packet_p->Header.PayloadLength, + Packet_p->Hash, (HashCallback_t)R15_Bulk_OutHashCallback, + (void *)Packet_p); + } else { + SET_PACKET_FLAGS(Packet_p, PACKET_CRC_STATE_MASK, BUF_PAYLOAD_CRC_CALCULATED); + memset(&Packet_p->Header.PayloadChecksum, 0x0, sizeof(uint32)); + //SET_PACKET_FLAGS(Packet_p, PACKET_CRC_STATE_MASK, BUF_HEADER_CRC_CALCULATED); + R15_SerializeHeader(Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER, &Packet_p->Header); + (void)QUEUE(Packet_p->Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Outbound_p, Packet_p); + } + } else { + (void)QUEUE(Packet_p->Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Outbound_p, Packet_p); + } + + /* mark packet as sent */ + SET_PACKET_FLAGS(BulkVector_p->Entries[ChunkId].Buffer_p, PACKET_TX_STATE_MASK, BUF_TX_SENDING); +} + +static void R15_Bulk_OutHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p) +{ + PacketMeta_t *Packet_p = (PacketMeta_t *)Param_p; + + SET_PACKET_FLAGS(Packet_p, PACKET_CRC_STATE_MASK, BUF_PAYLOAD_CRC_CALCULATED); + memcpy(&Packet_p->Header.PayloadChecksum, Hash_p, sizeof(uint32)); + + R15_SerializeHeader(Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER, &Packet_p->Header); + (void)QUEUE(Packet_p->Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Outbound_p, Packet_p); +} + + +static void R15_Bulk_ReadChunkCallBack(Communication_t *Communication_p, const void *const Timer_p, const void *const Data_p) +{ + R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p->State = WAIT_CHUNKS; + (void)QUEUE((Communication_p), FifoEnqueue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p, (void *)Data_p); +} + +static void R15_Bulk_RetransmitChunks_CallBack(const Communication_t *const Communication_p, const void *const Timer_p, const void *const Data_p) +{ + /* set all chunks for retransmision . Max retransmision is 3. */ + uint32 ChunkId; + PacketMeta_t *Packet_p; + + for (ChunkId = 0; ChunkId < R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p->Buffers; ChunkId++) { + Packet_p = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p->Entries[ChunkId].Buffer_p; + /* set packet as ready for sending. */ + SET_PACKET_FLAGS(Packet_p, PACKET_TX_STATE_MASK, BUF_TX_READY); + } + + R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p->State = SENDING_CHUNKS; +} + +static void R15_Bulk_GetListOfReceivedChunks(const TL_BulkVectorList_t *const BulkVector_p, uint32 *Chunks_p, uint8 *ChunkList_p) +{ + uint8 ChunkCounter; + *Chunks_p = 0; + + for (ChunkCounter = 0; ChunkCounter < BulkVector_p->Buffers; ChunkCounter++) { + if (NULL != BulkVector_p->Entries[ChunkCounter].Buffer_p) { + ChunkList_p[*Chunks_p] = ChunkCounter; + (*Chunks_p)++; + } + } +} + +#ifndef CFG_ENABLE_LOADER_TYPE +static boolean IsChunkReceived(Communication_t *Communication_p, uint32 ChunkId) +{ + PacketMeta_t *Packet_p = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p->Entries[ChunkId].Buffer_p; + + if (NULL != Packet_p) { + return CHECK_PACKET_FLAGS(Packet_p, BUF_ACK_READY) || CHECK_PACKET_FLAGS(Packet_p, BUF_ACKNOWLEDGED); + } else { + return FALSE; + } +} +#endif + +static uint32 R15_Bulk_GetChunkId(const PacketMeta_t *const Packet_p) +{ + BulkExtendedHeader_t BulkExtendedHeader = {0}; + + R15_DeserializeBulkExtendedHeader(&BulkExtendedHeader, Packet_p->ExtendedHeader_p); + + //lint -e(413,826) + return BulkExtendedHeader.AcksChunk; +} + +static TL_BulkVectorStatus_t R15_Bulk_GetVectorStatus(TL_BulkVectorList_t *BulkVector_p) +{ + uint32 ChunkCounter; + PacketMeta_t *Packet_p; + TL_BulkVectorStatus_t Status = VECTOR_COMPLETE; + + for (ChunkCounter = 0; ChunkCounter < BulkVector_p->Buffers; ChunkCounter++) { + Packet_p = BulkVector_p->Entries[ChunkCounter].Buffer_p; + + if (Packet_p == NULL || + !(CHECK_PACKET_FLAGS(Packet_p, BUF_ACK_READY) || CHECK_PACKET_FLAGS(Packet_p, BUF_ACKNOWLEDGED))) { + Status = VECTOR_NOT_COMPLETE; + } else { + if (Status == VECTOR_NOT_COMPLETE) { + Status = VECTOR_MISSING_CHUNK; + break; + } + } + } + + return Status; +} + +static uint32 R15_Bulk_GetTimerChunkRetransmision(const Communication_t *const Communication_p, uint32 Time, HandleFunction_t CallBack_p) +{ + Timer_t Timer; + + Timer.Time = Time; + Timer.PeriodicalTime = 0; + Timer.HandleFunction_p = (HandleFunction_t)CallBack_p; + Timer.Data_p = NULL; + Timer.Param_p = (void *)Communication_p; + + return TIMER(Communication_p, TimerGet_Fn)(OBJECT_TIMER(Communication_p), &Timer); +} + +static ErrorCode_e R15_Bulk_ReadRequestHandler(Communication_t *Communication_p, PacketMeta_t *Packet_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + BulkExtendedHeader_t ExtendedHeader = {0}; + TL_BulkVectorList_t *BulkVector_p = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p; + TL_BulkSessionID_Status_t BulkSessionIDStatus; +#ifndef CFG_ENABLE_LOADER_TYPE + boolean ACK_Read = FALSE; + uint32 Buffers; + BulkCommandReqCallback_t pcbf; +#endif + + R15_DeserializeBulkExtendedHeader(&ExtendedHeader, Packet_p->ExtendedHeader_p); + + // check the session ID of the received packet + BulkSessionIDStatus = R15_Bulk_CheckBulkSession(Communication_p, ExtendedHeader.Session); + VERIFY(BULK_SESSION_INVALID != BulkSessionIDStatus, E_INVALID_BULK_SESSION_ID); + +#ifdef CFG_ENABLE_LOADER_TYPE + + if (BULK_SESSION_NEW != BulkSessionIDStatus) { + // check witch chunks are acknowledged! + if (Packet_p->Header.PayloadLength > 0) { + if (!R15_Bulk_CheckAcknowledgedChunks(BulkVector_p, Packet_p->Payload_p)) { + /* mark all not ackonwledged chunks for retransmision */ + R15_Bulk_MarkNotAckChunks(BulkVector_p, Packet_p->Payload_p, ExtendedHeader.AcksChunk); + BulkVector_p->State = SENDING_CHUNKS; + } else { + BulkVector_p->State = WRITE_BULK_FINISH; + } + + /* Try to release the timer for the bulk session acknowledge */ + if (R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey > 0) { + (void)TIMER(Communication_p, TimerRelease_Fn)(OBJECT_TIMER(Communication_p), R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey); + R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey = 0; + } + } else { + if ((BulkVector_p->State == SENDING_CHUNKS) || (BulkVector_p->State == WAIT_BULK_ACK)) { + /* mark all chunks for retransmision */ + R15_Bulk_MarkNotAckAllChunks(BulkVector_p); + } else { + /* release the buffer for previous command BULK WRITE */ + uint32 Key = R15_Network_CreateUniqueKey(Packet_p, CMD_BULK_WRITE); + ReturnValue = R15_Network_CancelRetransmission(Communication_p, Key); + VERIFY((E_SUCCESS == ReturnValue) || (E_NOT_FOUND_ELEMENT_IN_RETRANSMISSION_LIST == ReturnValue), ReturnValue); + } + + BulkVector_p->State = SENDING_CHUNKS; + } + + ReturnValue = R15_Bulk_Process_Write(Communication_p, BulkVector_p); // state machine for WRITE BULK data + } + +#else + C_(printf("bulk_protocol.c(%d) Received READ packet!\n", __LINE__);) + C_(printf("bulk_protocol.c(%d) Session (%d)!\n", __LINE__, ExtendedHeader.Session);) + + /*ckeck the ACK */ + if (NULL != R15_TRANSPORT(Communication_p)->BulkCommandCallback_p) { + // check the session ID of the received packet + if (BULK_SESSION_NEW == BulkSessionIDStatus) { + /* request for new bulk session */ + // check the status of the current bulk session + if (Do_R15_Bulk_GetStatusSession(R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p) != BULK_SESSION_IDLE) { + if (BulkVector_p->State == WAIT_BULK_ACK) { + C_(printf("bulk_protocol.c(%d) Request for new session but current is not closed!\n", __LINE__);) + C_(printf("bulk_protocol.c(%d) Current: Session (%d)!\n", __LINE__, BulkVector_p->SessionId);) + C_(printf("bulk_protocol.c(%d) ReceivedPacket: Session (%d)!\n", __LINE__, ExtendedHeader.Session);) + + // close the current bulk session + (void)Do_R15_Bulk_CloseSession(Communication_p, BulkVector_p); //TODO: da se hendla return vrednosta! + + // notify session end + pcbf = (BulkCommandReqCallback_t)R15_TRANSPORT(Communication_p)->BulkCommandCallback_p; + pcbf(Communication_p->Object_p, &BulkVector_p->SessionId, &BulkVector_p->ChunkSize, &BulkVector_p->Offset, &BulkVector_p->Length, TRUE); + + // set bulk parameters for new bulk session + ACK_Read = FALSE; + SESSION(Communication_p) = ExtendedHeader.Session; + CHUNKSIZE(Communication_p) = ExtendedHeader.ChunkSize; + OFFSET(Communication_p) = ExtendedHeader.Offset; + LENGTH(Communication_p) = ExtendedHeader.Length; + pcbf(Communication_p->Object_p, &SESSION(Communication_p), &CHUNKSIZE(Communication_p), &OFFSET(Communication_p), &LENGTH(Communication_p), ACK_Read); + } else { + // can't be opened new bulk session until current session is not finished. + goto ErrorExit; + } + } else { + C_(printf("bulk_protocol.c(%d) Request for new bulk session!\n", __LINE__);) + // received request for new bulk session + ACK_Read = FALSE; + SESSION(Communication_p) = ExtendedHeader.Session; + CHUNKSIZE(Communication_p) = ExtendedHeader.ChunkSize; + OFFSET(Communication_p) = ExtendedHeader.Offset; + LENGTH(Communication_p) = ExtendedHeader.Length; + pcbf = (BulkCommandReqCallback_t)R15_TRANSPORT(Communication_p)->BulkCommandCallback_p; + pcbf(Communication_p->Object_p, &SESSION(Communication_p), &CHUNKSIZE(Communication_p), &OFFSET(Communication_p), &LENGTH(Communication_p), ACK_Read); + R15_Bulk_ClearBulkTmpParam(Communication_p); + } + } else { + // current bulk session + Buffers = ((ExtendedHeader.Length + ExtendedHeader.ChunkSize - 1) / ExtendedHeader.ChunkSize); + + if (((ExtendedHeader.AcksChunk == 0) && (Do_R15_Bulk_GetStatusSession(R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p) == BULK_SESSION_IDLE)) || (ExtendedHeader.AcksChunk == Buffers)) { + //BulkCommandReqCallback_t pcbf; + if (Buffers == ExtendedHeader.AcksChunk) { + C_(printf("bulk_protocol.c(%d) ACK for bulk session(%d)!\n", __LINE__, ExtendedHeader.Session);) + (void)TIMER(Communication_p, TimerRelease_Fn)(OBJECT_TIMER(Communication_p), R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey); + (void)Do_R15_Bulk_CloseSession(Communication_p, BulkVector_p); //TODO: da se hendla return vrednosta! + + // notify session end + pcbf = (BulkCommandReqCallback_t)R15_TRANSPORT(Communication_p)->BulkCommandCallback_p; + pcbf(Communication_p->Object_p, &BulkVector_p->SessionId, &BulkVector_p->ChunkSize, &BulkVector_p->Offset, &BulkVector_p->Length, TRUE); + } else { + C_(printf("bulk_protocol.c(%d) Request for new bulk session(%d)!\n", __LINE__, ExtendedHeader.Session);) + ACK_Read = FALSE; + SESSION(Communication_p) = ExtendedHeader.Session; + CHUNKSIZE(Communication_p) = ExtendedHeader.ChunkSize; + OFFSET(Communication_p) = ExtendedHeader.Offset; + LENGTH(Communication_p) = ExtendedHeader.Length; + + /* Try to release the timer for the bulk session acknowledge */ + if (R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey > 0) { + (void)TIMER(Communication_p, TimerRelease_Fn)(OBJECT_TIMER(Communication_p), R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey); // LCM MB bug fix: Timer should be released on request for retransmission + R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey = 0; + } + + pcbf = (BulkCommandReqCallback_t)R15_TRANSPORT(Communication_p)->BulkCommandCallback_p; + pcbf(Communication_p->Object_p, &SESSION(Communication_p), &CHUNKSIZE(Communication_p), &OFFSET(Communication_p), &LENGTH(Communication_p), ACK_Read); + R15_Bulk_ClearBulkTmpParam(Communication_p); + } + } else { + if (ExtendedHeader.AcksChunk == 0) { + /* mark all chunks for retransmision */ + R15_Bulk_MarkNotAckAllChunks(BulkVector_p); + } else { + /* mark all not ackonwledged chunks for retransmision */ + A_(printf("bulk_protocol.c (%d): Mark All NACK Chunks for Retransmission **\n", __LINE__);) + R15_Bulk_MarkNotAckChunks(BulkVector_p, Packet_p->Payload_p, ExtendedHeader.AcksChunk); + } + + BulkVector_p->State = SENDING_CHUNKS; + + /* Try to release the timer for the bulk session acknowledge */ + if (R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey > 0) { + (void)TIMER(Communication_p, TimerRelease_Fn)(OBJECT_TIMER(Communication_p), R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey); // LCM MB bug fix: Timer should be released on request for retransmission + R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey = 0; + } + } + } + } + +#endif + +ErrorExit: + /* release the buffer for command BULK READ */ + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); // TODO: proveri zosto ReturnValue se zema od ovde za posleden! + return ReturnValue; +} + +static ErrorCode_e R15_Bulk_DataRequestHandler(Communication_t *Communication_p, PacketMeta_t *Packet_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + BulkExtendedHeader_t ExtendedHeader = {0}; + TL_BulkVectorList_t *BulkVector_p = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p; + TL_BulkVectorList_t *PreviousBulkVector_p = &(R15_TRANSPORT(Communication_p)->PreviousBulkVector); + uint32 ChunksCount = 0; + uint8 ChunksList[MAX_BULK_TL_PROCESSES]; +#ifndef CFG_ENABLE_LOADER_TYPE + uint32 ChunkId = 0; + BulkDataReqCallback_t pcbf; +#endif + + R15_DeserializeBulkExtendedHeader(&ExtendedHeader, Packet_p->ExtendedHeader_p); + +#ifdef CFG_ENABLE_LOADER_TYPE + + if (ExtendedHeader.AcksChunk == 0) { + BulkVector_p->State = WAIT_CHUNKS; + R15_TRANSPORT(Communication_p)->BulkHandle.TimerKey = 0; + } + + if (PreviousBulkVector_p->SessionId == BulkVector_p->SessionId) { + // make the list of received chunks + R15_Bulk_GetListOfReceivedChunks(PreviousBulkVector_p, &ChunksCount, ChunksList); + // send read ACK for previous session + ReturnValue = R15_Bulk_SendReadRequest(Communication_p, PreviousBulkVector_p, ChunksCount, ChunksList, NULL); + // release the buffer used for this data chunk + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + goto ErrorExit; + } + + /* cancel retransmission, release buffer */ + ReturnValue = R15_Network_CancelRetransmission(Communication_p, R15_Network_CreateUniqueKey(Packet_p, CMD_BULK_READ)); + VERIFY(((E_SUCCESS == ReturnValue) || (ReturnValue == E_NOT_FOUND_ELEMENT_IN_RETRANSMISSION_LIST)), ReturnValue); + /* state machine for READ BULK data */ + ReturnValue = R15_Bulk_Process_Read(Communication_p, BulkVector_p, Packet_p); +#else + + if (Do_R15_Bulk_GetStatusSession(BulkVector_p) == BULK_SESSION_IDLE) { + //no opened current session + // make the list of received chunks + R15_Bulk_GetListOfReceivedChunks(PreviousBulkVector_p, &ChunksCount, ChunksList); + // send read ACK for previous session + ReturnValue = R15_Bulk_SendReadRequest(Communication_p, PreviousBulkVector_p, ChunksCount, ChunksList, NULL); + // release the buffer used for this data chunk + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + } else { + if (NULL != R15_TRANSPORT(Communication_p)->BulkDataCallback_p) { + ChunkId = ExtendedHeader.AcksChunk; + + if (!IsChunkReceived(Communication_p, ChunkId)) { + SESSION(Communication_p) = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p->SessionId; + CHUNKSIZE(Communication_p) = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p->ChunkSize; + OFFSET(Communication_p) = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p->Offset; + LENGTH(Communication_p) = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p->Length; + TRANSFEREDLENGTH(Communication_p) += CHUNKSIZE(Communication_p); + pcbf = (BulkDataReqCallback_t)R15_TRANSPORT(Communication_p)->BulkDataCallback_p; + pcbf(Communication_p->Object_p, &SESSION(Communication_p), &CHUNKSIZE(Communication_p), &OFFSET(Communication_p), &LENGTH(Communication_p), &TOTALLENGTH(Communication_p), &TRANSFEREDLENGTH(Communication_p)); + C_(printf("S(%d) L(%d) CS(%d)\n", SESSION(Communication_p), LENGTH(Communication_p), CHUNKSIZE(Communication_p));) //xvsvlpi + } + } + + /* cancel retransmission, release buffer */ + ReturnValue = R15_Network_CancelRetransmission(Communication_p, R15_Network_CreateUniqueKey(Packet_p, CMD_BULK_READ)); + VERIFY(((E_SUCCESS == ReturnValue) || (ReturnValue == E_NOT_FOUND_ELEMENT_IN_RETRANSMISSION_LIST)), ReturnValue); + /* state machine for READ BULK data */ + ReturnValue = R15_Bulk_Process_Read(Communication_p, BulkVector_p, Packet_p); + } + +#endif + +ErrorExit: + return ReturnValue; +} + + +/* + * Check the bulk session ID. Can be new bulk session or the current opened bulk + * session. Session ID can't be the '0'. Allowed Session ID is 1-65535. + * + * @param[in] Communication_p Communication module context. + * @param[in] SessionId Session ID from the received bulk packet. + * + * @retval BULK_SESSION_INVALID If the Session ID=0. + * @retval BULK_SESSION_CURRENT If the session ID is same as current session ID. + * @retval BULK_SESSION_NEW New bulk session + */ +static TL_BulkSessionID_Status_t R15_Bulk_CheckBulkSession(Communication_t *Communication_p, uint16 SessionId) +{ + TL_BulkSessionID_Status_t ReturnStatus = BULK_SESSION_INVALID; + TL_BulkVectorList_t *CurrentBulkVector_p = R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p; +#ifndef CFG_ENABLE_LOADER_TYPE + TL_BulkVectorList_t *PreviousBulkVector_p = &(R15_TRANSPORT(Communication_p)->PreviousBulkVector); +#endif + + if (SessionId == 0) { + return ReturnStatus; + } + +#ifndef CFG_ENABLE_LOADER_TYPE + + if (PreviousBulkVector_p == NULL) { + return BULK_SESSION_NEW; + } + + if ((PreviousBulkVector_p->SessionId != 0) && (Do_R15_Bulk_GetStatusSession(CurrentBulkVector_p) != BULK_IDLE_STATE)) { +#endif + + //lint --e(539) + if (CurrentBulkVector_p->SessionId == SessionId) { + ReturnStatus = BULK_SESSION_CURRENT; + } else { + ReturnStatus = BULK_SESSION_NEW; + } + +#ifndef CFG_ENABLE_LOADER_TYPE + } else { + if (PreviousBulkVector_p->SessionId < SessionId || + (SessionId == 1 && PreviousBulkVector_p->SessionId > SessionId)) { + ReturnStatus = BULK_SESSION_NEW; + } else { + ReturnStatus = BULK_SESSION_INVALID; + } + } + +#endif + return ReturnStatus; +} + +#ifndef CFG_ENABLE_LOADER_TYPE +/* + * Clear temporary saved bulk parameters + * + * @param[in] Communication_p Communication module context. + * + * return none. + */ +static void R15_Bulk_ClearBulkTmpParam(Communication_t *Communication_p) +{ + SESSION(Communication_p) = 0; + CHUNKSIZE(Communication_p) = 0; + OFFSET(Communication_p) = 0; + LENGTH(Communication_p) = 0; +} +#endif + +/** @} */ +/** @} */ +/** @} */ diff --git a/lcmodule/source/cnh1605204_ldr_transport_layer/source/command_protocol.c b/lcmodule/source/cnh1605204_ldr_transport_layer/source/command_protocol.c new file mode 100644 index 0000000..08b4819 --- /dev/null +++ b/lcmodule/source/cnh1605204_ldr_transport_layer/source/command_protocol.c @@ -0,0 +1,311 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + * @addtogroup r15_family + * @{ + * @addtogroup command_protocol + * @{ + */ +/******************************************************************************* + * Includes + ******************************************************************************/ +#include "t_basicdefinitions.h" +#include "r_command_protocol.h" +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include "r_communication_service.h" +#include "r_r15_family.h" +#include "r_r15_network_layer.h" +#include "r_r15_transport_layer.h" +#include "t_r15_header.h" +#include "t_security_algorithms.h" +#include "r_debug.h" +#include "r_debug_macro.h" +#include "r_r15_header.h" + +/******************************************************************************* + * File scope types, constants and variables + ******************************************************************************/ + +/******************************************************************************* + * Declaration of file local functions + ******************************************************************************/ +static ErrorCode_e ProcessAcknowledgement(Communication_t *Communication_p, const PacketMeta_t *Packet_p, const uint16 *const SessionState_p); +static ErrorCode_e ProcessCommand(Communication_t *Communication_p, PacketMeta_t *Packet_p, uint16 *SessionState); +static ErrorCode_e ProcessGeneralResponse(Communication_t *Communication_p, PacketMeta_t *Packet_p, uint16 *SessionState_p); +static ErrorCode_e SendAcknowledge(Communication_t *Communication_p, const PacketMeta_t *const Packet_p); +static uint16 GetSendSession(const Communication_t *const Communication_p, CommandData_t *CmdData_p); +static ErrorCode_e DispatchCommand(Communication_t *Communication_p, PacketMeta_t *Packet_p); + +/******************************************************************************* + * Definition of external functions + ******************************************************************************/ +/* + * Reset the Session counters. + * + * @param [in] Communication_p Communication module context. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e Do_R15_Command_ResetSessionCounters(const Communication_t *const Communication_p) +{ + /* Iintialize the session counters */ + R15_TRANSPORT(Communication_p)->SessionStateIn = 0; + R15_TRANSPORT(Communication_p)->SessionStateOut = 0; + + return E_SUCCESS; +} + + +/* + * Sends command packet with command protocol. + * + * @param [in] Communication_p Communication module context. + * @param [in] CmdData_p Pointer to the command data. + * + * @retval E_SUCCESS After successful execution. + * @retval E_INVALID_INPUT_PARAMETERS If CmdData_p is NULL. + */ +ErrorCode_e Do_R15_Command_Send(Communication_t *Communication_p, CommandData_t *CmdData_p) +{ + CommandExtendedHeader_t ExtendedHeader; + R15_Header_t Header; + SendData_LP_t Param; + + if (NULL == CmdData_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + Param.Header_p = &Header; + Param.ExtendedHeader_p = &ExtendedHeader; + Param.Payload_p = CmdData_p->Payload.Data_p; + + Header.Protocol = COMMAND_PROTOCOL; + Header.Flags = Communication_p->CurrentFamilyHash; + Header.PayloadLength = CmdData_p->Payload.Size; + Header.PayloadChecksum = 0; + Header.ExtendedHeaderLength = COMMAND_EXTENDED_HEADER_LENGTH; + Header.ExtendedHeaderChecksum = 0; + + ExtendedHeader.SessionState = GetSendSession(Communication_p, CmdData_p); + ExtendedHeader.Command = CmdData_p->CommandNr; + ExtendedHeader.CommandGroup = CmdData_p->ApplicationNr; + + // TODO: Don't we need a timer callback for this to actually do something? + Param.Time = R15_TIMEOUTS(Communication_p)->TCACK; //ACK_TIMEOUT_IN_MS; + Param.TimerCallBackFn_p = NULL; //NOTE: the timer will be assigned in "R15_Transport_Send" + + C_(printf("command_protocol.c (%d): R15_Transport_Send! Type:%d Session:%d Command:%d CommandGroup:%d\n", __LINE__, CmdData_p->Type, ExtendedHeader.SessionState, ExtendedHeader.Command, ExtendedHeader.CommandGroup);) + + return R15_Transport_Send(Communication_p, &Param); +} + +/* + * Decode received command. + * + * @param [in] Communication_p Communication module context. + * @param [in] Packet_p Pointer to the received buffer. + * + * @retval E_SUCCESS After successful execution. + * @retval E_INVALID_INPUT_PARAMETERS if Packet_p is NULL. + */ +ErrorCode_e R15_Command_Process(Communication_t *Communication_p, PacketMeta_t *Packet_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + CommandExtendedHeader_t CommandExtendedHeader = {0}; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + R15_DeserializeCommandExtendedHeader(&CommandExtendedHeader, Packet_p->ExtendedHeader_p); + + switch (CommandExtendedHeader.SessionState & MASK_SELECT_STATE) { + case COMMAND_PACKAGE: + ReturnValue = ProcessCommand(Communication_p, Packet_p, &(R15_TRANSPORT(Communication_p)->SessionStateIn)); + break; + + case ACK_PACKAGE: + ReturnValue = ProcessAcknowledgement(Communication_p, Packet_p, &(R15_TRANSPORT(Communication_p)->SessionStateOut)); + break; + + case GENERAL_RESPONSE_PACKAGE: + ReturnValue = ProcessGeneralResponse(Communication_p, Packet_p, &(R15_TRANSPORT(Communication_p)->SessionStateOut)); + break; + + case ACK_GENERAL_RESPONSE_PACKAGE: + ReturnValue = ProcessAcknowledgement(Communication_p, Packet_p, &(R15_TRANSPORT(Communication_p)->SessionStateIn)); + break; + + default: + ReturnValue = E_SUCCESS; + break; + } + + return ReturnValue; +} + +/******************************************************************************* + * Definition of internal functions + ******************************************************************************/ +static uint16 GetSendSession(const Communication_t *const Communication_p, CommandData_t *CmdData_p) +{ + uint16 value; + + if (CmdData_p->Type == GENERAL_RESPONSE) { + value = CmdData_p->SessionNr << 2 | GENERAL_RESPONSE_PACKAGE; + } else { + R15_TRANSPORT(Communication_p)->SessionStateOut += 4; + value = R15_TRANSPORT(Communication_p)->SessionStateOut; + CmdData_p->SessionNr = value >> 2; + } + + return value; +} + + +static ErrorCode_e ProcessAcknowledgement(Communication_t *Communication_p, const PacketMeta_t *Packet_p, const uint16 *const SessionState_p) +{ + ErrorCode_e ReturnValue = E_GENERAL_FATAL_ERROR; + uint32 Key; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + Key = R15_Network_CreateUniqueKey(Packet_p, 0); + (void)R15_Network_CancelRetransmission(Communication_p, Key); + B_(printf("command_protocol.c (%d): Received Acknowledge!\n", __LINE__);) + + ReturnValue = R15_Network_PacketRelease(Communication_p, (PacketMeta_t *)Packet_p); + return ReturnValue; +} + + +static ErrorCode_e ProcessCommand(Communication_t *Communication_p, PacketMeta_t *Packet_p, uint16 *SessionState_p) +{ + ErrorCode_e ReturnValue; + CommandExtendedHeader_t CommandExtendedHeader = {0}; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + R15_DeserializeCommandExtendedHeader(&CommandExtendedHeader, Packet_p->ExtendedHeader_p); + + if ((CommandExtendedHeader.SessionState & SESSION_MASK) == (*SessionState_p & SESSION_MASK) + 4) { + *SessionState_p += 4; + } else { + ReturnValue = SendAcknowledge(Communication_p, Packet_p); + + if (E_SUCCESS != ReturnValue) { + return ReturnValue; + } + + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + return ReturnValue; + } + + return DispatchCommand(Communication_p, Packet_p); +} + +static ErrorCode_e ProcessGeneralResponse(Communication_t *Communication_p, PacketMeta_t *Packet_p, uint16 *SessionState_p) +{ + ErrorCode_e ReturnValue; + CommandExtendedHeader_t ExtendedHeader = {0}; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + R15_DeserializeCommandExtendedHeader(&ExtendedHeader, Packet_p->ExtendedHeader_p); + + if ((ExtendedHeader.SessionState & SESSION_MASK) > (*SessionState_p & SESSION_MASK)) { + ReturnValue = SendAcknowledge(Communication_p, Packet_p); + + if (E_SUCCESS != ReturnValue) { + return ReturnValue; + } + + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + return ReturnValue; + } + + return DispatchCommand(Communication_p, Packet_p); +} + + +static ErrorCode_e DispatchCommand(Communication_t *Communication_p, PacketMeta_t *Packet_p) +{ + ErrorCode_e ReturnValue; + CommandExtendedHeader_t ExtendedHeader = {0}; + CommandData_t CmdData; + + ReturnValue = SendAcknowledge(Communication_p, Packet_p); + + if (E_SUCCESS != ReturnValue) { + return E_SUCCESS; + } + + R15_DeserializeCommandExtendedHeader(&ExtendedHeader, Packet_p->ExtendedHeader_p); + + CmdData.Type = (CommandType_t)(ExtendedHeader.SessionState & MASK_SELECT_STATE); + CmdData.CommandNr = ExtendedHeader.Command; + CmdData.ApplicationNr = ExtendedHeader.CommandGroup; + CmdData.SessionNr = ExtendedHeader.SessionState >> 2; + CmdData.Payload.Size = Packet_p->Header.PayloadLength; + CmdData.Payload.Data_p = NULL; + + if (0 != CmdData.Payload.Size) { + CmdData.Payload.Data_p = (uint8 *)malloc(Packet_p->Header.PayloadLength); + + if (NULL == CmdData.Payload.Data_p) { + return E_ALLOCATE_FAILED; + } + + memcpy(CmdData.Payload.Data_p, Packet_p->Payload_p, Packet_p->Header.PayloadLength); + } + + ReturnValue = R15_Network_PacketRelease(Communication_p, Packet_p); + + ReturnValue = Communication_p->Do_CEH_Call_Fn(OBJECT_CEH_CALL(Communication_p), &CmdData); + + if (NULL != CmdData.Payload.Data_p) { + free(CmdData.Payload.Data_p); + CmdData.Payload.Data_p = NULL; + } + + return ReturnValue; +} + +static ErrorCode_e SendAcknowledge(Communication_t *Communication_p, const PacketMeta_t *const Packet_p) +{ + CommandExtendedHeader_t ExtendedHeader; + R15_Header_t Header; + SendData_LP_t Param; + + memcpy(&ExtendedHeader, Packet_p->ExtendedHeader_p, COMMAND_EXTENDED_HEADER_LENGTH); + ExtendedHeader.SessionState++; + memcpy(&Header, &Packet_p->Header, HEADER_LENGTH); + Header.Flags = Communication_p->CurrentFamilyHash; + Header.PayloadLength = 0; + Header.PayloadChecksum = 0; + Header.ExtendedHeaderChecksum = 0; + + Param.Header_p = &Header; + Param.ExtendedHeader_p = &ExtendedHeader; + Param.Payload_p = NULL; + Param.Time = 0; + Param.TimerCallBackFn_p = NULL; + + return R15_Transport_Send(Communication_p, &Param); +} + +/** @} */ +/** @} */ +/** @} */ diff --git a/lcmodule/source/cnh1605204_ldr_transport_layer/source/protrom_protocol.c b/lcmodule/source/cnh1605204_ldr_transport_layer/source/protrom_protocol.c new file mode 100644 index 0000000..bf5d5dd --- /dev/null +++ b/lcmodule/source/cnh1605204_ldr_transport_layer/source/protrom_protocol.c @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + * @addtogroup protrom_family + * @{ + * @addtogroup protrom_protocol + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include <stdlib.h> +#include <string.h> + +#include "r_protrom_family.h" +#include "r_protrom_protocol.h" +#include "r_protrom_network.h" +#include "r_protrom_transport.h" +#include "r_communication_service.h" +#include "r_debug_macro.h" + +/******************************************************************************* + * File scope types, constants and variables + ******************************************************************************/ + +/******************************************************************************* + * Definition of external functions + ******************************************************************************/ + +/* + * Decode received command, and execute. + * + * @param [in] Communication_p Communication module context. + * @param [in] Packet_p Pointer to the received buffer. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e Protrom_Process(const Communication_t *const Communication_p, Protrom_Packet_t *Packet_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + CommandData_t CmdData; + uint8 *DataTmp_p; + + if (NULL == Packet_p) { + return E_INVALID_INPUT_PARAMETERS; + } + + //if(PROTO_PROTROM == ((Protrom_Packet_t *)Packet_p)->Header.Protocol) + // return E_INVALID_INPUT_PARAMETERS; + + if (NULL != Communication_p->Do_CEH_Call_Fn) { + CmdData.Payload.Size = Packet_p->Header.PayloadLength + PROTROM_HEADER_LENGTH + PROTROM_CRC_LENGTH; + DataTmp_p = (uint8 *)malloc(CmdData.Payload.Size); + + if (NULL == DataTmp_p) { + return E_ALLOCATE_FAILED; + } + + CmdData.Payload.Data_p = DataTmp_p; + memcpy(CmdData.Payload.Data_p, Packet_p->Buffer_p, CmdData.Payload.Size); + + free(Packet_p->Buffer_p); + free(Packet_p); + + ReturnValue = Communication_p->Do_CEH_Call_Fn(OBJECT_CEH_CALL(Communication_p), &CmdData); + + if (NULL != CmdData.Payload.Data_p) { + free(CmdData.Payload.Data_p); + CmdData.Payload.Data_p = NULL; + } + } + + return ReturnValue; +} + +/** @} */ +/** @} */ +/** @} */ diff --git a/lcmodule/source/cnh1605204_ldr_transport_layer/source/protrom_transport.c b/lcmodule/source/cnh1605204_ldr_transport_layer/source/protrom_transport.c new file mode 100644 index 0000000..ef50be7 --- /dev/null +++ b/lcmodule/source/cnh1605204_ldr_transport_layer/source/protrom_transport.c @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + * @addtogroup protrom_family + * @{ + * @addtogroup ldr_transport_layer + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include <stdlib.h> +#include <string.h> + +#include "c_system.h" +#include "t_basicdefinitions.h" +#include "r_debug.h" +#include "r_debug_macro.h" +#include "r_protrom_family.h" +#include "r_protrom_header.h" +#include "r_protrom_transport.h" +#include "r_protrom_network.h" +#include "r_protrom_protocol.h" +#include "r_communication_service.h" +#include "t_security_algorithms.h" +#include "r_memmory_utils.h" + +/******************************************************************************* + * Declaration of file local functions + ******************************************************************************/ +static void Protrom_Transport_OutHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p); + +/******************************************************************************* + * File scope types, constants and variables + ******************************************************************************/ + +/******************************************************************************* + * Definition of external functions + ******************************************************************************/ + +/* + * Handles all registered TL processes for PROTROM protocol family. + * + * @param [in] Communication_p Communication module context. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e Protrom_Transport_Poll(Communication_t *Communication_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + Protrom_Packet_t *Packet_p = NULL; + + Protrom_Network_ReceiverHandler(Communication_p); + Packet_p = (Protrom_Packet_t *)QUEUE(Communication_p, FifoDequeue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Inbound_p); + + if (NULL == Packet_p) { + return E_ALLOCATE_FAILED; + } + + ReturnValue = Protrom_Process(Communication_p, Packet_p); + + return ReturnValue; +} + +/* + * Function for sending packet in PROTROM protocol family. + * + * @param [in] Communication_p Communication module context. + * @param [in] InputDataIn_p Pointer to the input data. + * + * @retval E_SUCCESS After successful execution. + * @retval E_FAILED_TO_ALLOCATE_COMM_BUFFER Failed to allocate communication + * buffer. + */ +ErrorCode_e Protrom_Transport_Send(Communication_t *Communication_p, void *InputDataIn_p) +{ + Protrom_Packet_t *Packet_p = NULL; + Protrom_SendData_LP_t *InputData_p = (Protrom_SendData_LP_t *)InputDataIn_p; + + Packet_p = (Protrom_Packet_t *) malloc(sizeof(Protrom_Packet_t)); + + if (NULL == Packet_p) { + return E_ALLOCATE_FAILED; + } + + Packet_p->Header = *InputData_p->Header_p; + Packet_p->Buffer_p = (uint8 *)malloc(Packet_p->Header.PayloadLength + PROTROM_HEADER_LENGTH + PROTROM_CRC_LENGTH); + + if (NULL == Packet_p->Buffer_p) { + BUFFER_FREE(Packet_p); + return E_ALLOCATE_FAILED; + } + + Protrom_SerializeHeader(Packet_p->Buffer_p, &Packet_p->Header); + + if (NULL != InputData_p->Payload_p) { + /* setup payload for calculation */ + memcpy(Packet_p->Buffer_p + PROTROM_HEADER_LENGTH, InputData_p->Payload_p, Packet_p->Header.PayloadLength); + + /* Calculate Payload CRC */ + Packet_p->Communication_p = Communication_p; + + Communication_p->HashDevice_p->Calculate(OBJECT_HASH(Communication_p), Communication_p->CurrentFamilyHash, + Packet_p->Buffer_p, Packet_p->Header.PayloadLength + PROTROM_HEADER_LENGTH, + (uint8 *)&Packet_p->CRC, (HashCallback_t)Protrom_Transport_OutHashCallback, + (void *) Packet_p); + } else { + //@todo error no payload + } + + /* The packet's buffer and the packet resources are + * freed in the send callback function */ + + /* coverity[leaked_storage] */ + return E_SUCCESS; +} + +/******************************************************************************* + * Definition of internal functions + ******************************************************************************/ + +/* + * Callback function for handling calculated data. + * + * @param [in] Data_p Pointer to the data buffer for calculation. + * @param [in] Length Length of the data for calculation. + * @param [out] Hash_p Pointer to buffer with calculated hash. + * @param [in] Param_p Pointer to extra parameters. + * + * @return none. + */ +static void Protrom_Transport_OutHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p) +{ + Protrom_Packet_t *Packet_p = (Protrom_Packet_t *)Param_p; + + memcpy(&Packet_p->CRC, Hash_p, sizeof(uint16)); + memcpy((uint8 *)((Packet_p->Buffer_p) + PROTROM_HEADER_LENGTH + (Packet_p->Header.PayloadLength)), Hash_p, sizeof(uint16)); + Protrom_SerializeHeader(Packet_p->Buffer_p, &Packet_p->Header); + (void)QUEUE(Packet_p->Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Outbound_p, Packet_p); +} + +/** @} */ +/** @} */ +/** @} */ diff --git a/lcmodule/source/cnh1605204_ldr_transport_layer/source/r15_transport_layer.c b/lcmodule/source/cnh1605204_ldr_transport_layer/source/r15_transport_layer.c new file mode 100644 index 0000000..d55395c --- /dev/null +++ b/lcmodule/source/cnh1605204_ldr_transport_layer/source/r15_transport_layer.c @@ -0,0 +1,309 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + * @addtogroup r15_family + * @{ + * @addtogroup ldr_transport_layer + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include "c_system.h" +#include "r_r15_transport_layer.h" +#include <stdlib.h> +#include <string.h> +#include "r_basicdefinitions.h" +#include "t_time_utilities.h" +#include "r_debug.h" +#include "r_debug_macro.h" +#include "r_r15_header.h" +#include "r_command_protocol.h" +#include "r_bulk_protocol.h" +#include "r_r15_network_layer.h" +#include "r_r15_family.h" +#include "r_communication_service.h" +#include "t_security_algorithms.h" + +/******************************************************************************* + * Declaration of file local functions + ******************************************************************************/ +static Timer_t *TimerSet(PacketMeta_t *Packet_p, const SendData_LP_t *const InputData_p, Communication_t *Communication_p); +static void R15_Transport_OutHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p); + +/******************************************************************************* + * File scope types, constants and variables + ******************************************************************************/ + +/******************************************************************************* + * Definition of external functions + ******************************************************************************/ + +/* + * Initializes the transport layer for R15 protocol family. + * + * @param [in] Communication_p Communication module context. + * + * @retval E_SUCCESS After successful execution. + * @retval E_FAILED_TO_INIT_TL Unsuccessful initialization. + * @retval E_ALLOCATE_FAILED Failed to allocate memory space. + */ +ErrorCode_e R15_Transport_Initialize(const Communication_t *const Communication_p) +{ + int VectorCounter; + + /* Iintialize the session counters for command protocol*/ + R15_TRANSPORT(Communication_p)->SessionStateIn = 0; + R15_TRANSPORT(Communication_p)->SessionStateOut = 0; + + /* Iintialize the session counter for bulk protocol*/ + R15_TRANSPORT(Communication_p)->BulkSessionCounter = 0; + + /* initialize the default timeouts */ + R15_TIMEOUTS(Communication_p)->TCACK = ACK_TIMEOUT_IN_MS; + R15_TIMEOUTS(Communication_p)->TBCR = BULK_COMMAND_RECEIVING_TIMEOUT; + R15_TIMEOUTS(Communication_p)->TBDR = BULK_DATA_RECEIVING_TIMEOUT; + + for (VectorCounter = 0; VectorCounter < MAX_BULK_TL_PROCESSES; VectorCounter++) { + R15_TRANSPORT(Communication_p)->BulkVectorList[VectorCounter].Status = BULK_SESSION_IDLE; + } + + memset(&(R15_TRANSPORT(Communication_p)->PreviousBulkVector), 0x00, sizeof(TL_BulkVectorList_t)); + R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p = NULL; + + return E_SUCCESS; +} + +/* + * Shut Down the transport layer for R15 protocol family. + * + * @param [in] Communication_p Communication module context. + + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e R15_Transport_Shutdown(const Communication_t *const Communication_p) +{ + return E_SUCCESS; +} + +/* + * Handles all registered TL processes for R15 protocol family. + * + * @param [in] Communication_p Communication module context. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e R15_Transport_Poll(Communication_t *Communication_p) +{ + ErrorCode_e ReturnValue = E_GENERAL_FATAL_ERROR; +#ifndef CFG_ENABLE_LOADER_TYPE + PacketMeta_t *Packet_p = NULL; + + ReturnValue = R15_Network_ReceiverHandler(Communication_p); + VERIFY(E_SUCCESS == ReturnValue, ReturnValue); + + ReturnValue = R15_Network_TransmiterHandler(Communication_p); + VERIFY(E_SUCCESS == ReturnValue, ReturnValue); +#endif + + if (BULK_SESSION_IDLE != Do_R15_Bulk_GetStatusSession(R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p)) { + ReturnValue = R15_Bulk_Process_Write(Communication_p, R15_TRANSPORT(Communication_p)->BulkHandle.BulkVector_p); + VERIFY(E_SUCCESS == ReturnValue, ReturnValue); + } + + ReturnValue = R15_NETWORK(Communication_p)->Outbound.LCM_Error; + VERIFY(E_SUCCESS == ReturnValue, ReturnValue); + +#ifndef CFG_ENABLE_LOADER_TYPE + + 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: + return R15_Bulk_Process(Communication_p, Packet_p); + case PROTO_COMMAND: + return R15_Command_Process(Communication_p, Packet_p); + default: + return E_SUCCESS; + } + } + +#endif + +ErrorExit: + return ReturnValue; +} + + +/* + * Function for sending packet in R15 protocol family. + * + * @param [in] Communication_p Communication module context. + * @param [in] InputDataIn_p Pointer to the input data. + * + * @retval E_SUCCESS After successful execution. + * @retval E_FAILED_TO_ALLOCATE_COMM_BUFFER Failed to allocate communication + * buffer. + */ +ErrorCode_e R15_Transport_Send(Communication_t *Communication_p, void *InputDataIn_p) +{ + PacketMeta_t *Packet_p; + SendData_LP_t *InputData_p = (SendData_LP_t *)InputDataIn_p; + + if (InputData_p->Header_p->Protocol == BULK_PROTOCOL && (((BulkExtendedHeader_t *)InputData_p->ExtendedHeader_p)->TypeFlags & MASK_BULK_COMMAND_SELECT) == CMD_BULK_DATA) { + Packet_p = R15_Network_PacketAllocate(Communication_p, BULK_BUFFER_SIZE); + } else { + Packet_p = R15_Network_PacketAllocate(Communication_p, COMMAND_BUFFER_SIZE); + } + + if (NULL == Packet_p) { + A_(printf("r15_transport_layer.c (%d): ** Failed to get available buffers! **\n", __LINE__);) + return E_FAILED_TO_ALLOCATE_COMM_BUFFER; + } + + Packet_p->Resend = 0; + Packet_p->CallBack_p = NULL; + + Packet_p->Timer_p = TimerSet(Packet_p, InputData_p, Communication_p); + Packet_p->Header = *InputData_p->Header_p; + /* serialize and calculate extended header */ + Packet_p->ExtendedHeader_p = Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER + ALIGNED_HEADER_LENGTH; + R15_SerializeExtendedHeader(Packet_p->ExtendedHeader_p, InputData_p->Header_p->Protocol, InputData_p->ExtendedHeader_p, &(Packet_p->Header.ExtendedHeaderChecksum)); + if (Packet_p->Header.ExtendedHeaderLength == COMMAND_EXTENDED_HEADER_LENGTH) { + Packet_p->Payload_p = Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER + ALIGNED_HEADER_LENGTH + ALIGNED_COMMAND_EXTENDED_HEADER_LENGTH; + } else { + Packet_p->Payload_p = Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER + ALIGNED_HEADER_LENGTH + ALIGNED_BULK_EXTENDED_HEADER_LENGTH; + } + if (NULL != InputData_p->Payload_p) { + /* setup payload for calculation */ + memcpy(Packet_p->Payload_p, InputData_p->Payload_p, Packet_p->Header.PayloadLength); + + /* Calculate Payload CRC */ + Packet_p->Communication_p = Communication_p; + + if (HASH_NONE != Packet_p->Header.Flags) { + Communication_p->HashDevice_p->Calculate(OBJECT_HASH(Communication_p), + (HashType_e)Packet_p->Header.Flags, + (void *)Packet_p->Payload_p, Packet_p->Header.PayloadLength, + Packet_p->Hash, (HashCallback_t)R15_Transport_OutHashCallback, + (void *)Packet_p); + } else { + SET_PACKET_FLAGS(Packet_p, PACKET_CRC_STATE_MASK, BUF_PAYLOAD_CRC_CALCULATED); + memset(&Packet_p->Header.PayloadChecksum, 0x0, sizeof(uint32)); + R15_SerializeHeader(Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER, &Packet_p->Header); + + (void)QUEUE(Packet_p->Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Outbound_p, Packet_p); + } + } else { + R15_SerializeHeader(Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER, &Packet_p->Header); + + (void)QUEUE(Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Communication_p), Communication_p->Outbound_p, Packet_p); + } + + return E_SUCCESS; +} + +/* + * Function for setting the timeouts in the R15 protocol family. + * + * @param [in] Communication_p Communication module context. + * @param [in] TimeoutData_p Pointer to the input data with all timeouts. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e R15_SetProtocolTimeouts(Communication_t *Communication_p, void *TimeoutData_p) +{ + ErrorCode_e ReturnValue = E_INVALID_INPUT_PARAMETERS; + R15_Timeouts_t *NewTimeoutData_p = (R15_Timeouts_t *)TimeoutData_p; + VERIFY(NULL != TimeoutData_p, E_INVALID_INPUT_PARAMETERS); + + R15_TIMEOUTS(Communication_p)->TCACK = NewTimeoutData_p->TCACK; + R15_TIMEOUTS(Communication_p)->TBCR = NewTimeoutData_p->TBCR; + R15_TIMEOUTS(Communication_p)->TBDR = NewTimeoutData_p->TBDR; + ReturnValue = E_SUCCESS; + +ErrorExit: + return ReturnValue; +} + +/* + * Function for getting the timeouts in the R15 protocol family. + * + * @param [in] Communication_p Communication module context. + * @param [out] TimeoutData_p Return all defined timeouts. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e R15_GetProtocolTimeouts(Communication_t *Communication_p, void *TimeoutData_p) +{ + ErrorCode_e ReturnValue = E_INVALID_INPUT_PARAMETERS; + VERIFY(NULL != TimeoutData_p, E_INVALID_INPUT_PARAMETERS); + + ((R15_Timeouts_t *)TimeoutData_p)->TCACK = R15_TIMEOUTS(Communication_p)->TCACK; + ((R15_Timeouts_t *)TimeoutData_p)->TBCR = R15_TIMEOUTS(Communication_p)->TBCR; + ((R15_Timeouts_t *)TimeoutData_p)->TBDR = R15_TIMEOUTS(Communication_p)->TBDR; + ReturnValue = E_SUCCESS; + +ErrorExit: + return ReturnValue; +} + + +/* + * Callback function for handling calculated data. + * + * @param [in] Data_p Pointer to the data buffer for calculation. + * @param [in] Length Length of the data for calculation. + * @param [out] Hash_p Pointer to buffer with calculated hash. + * @param [in] Param_p Pointer to extra parameters. + * + * @return none. + */ +static void R15_Transport_OutHashCallback(const void *const Data_p, uint32 Length, const uint8 *const Hash_p, void *Param_p) +{ + PacketMeta_t *Packet_p = (PacketMeta_t *)Param_p; + + SET_PACKET_FLAGS(Packet_p, PACKET_CRC_STATE_MASK, BUF_PAYLOAD_CRC_CALCULATED); + memcpy(&Packet_p->Header.PayloadChecksum, Hash_p, sizeof(uint32)); + R15_SerializeHeader(Packet_p->Buffer_p + HEADER_OFFSET_IN_BUFFER, &Packet_p->Header); + + (void)QUEUE(Packet_p->Communication_p, FifoEnqueue_Fn)(OBJECT_QUEUE(Packet_p->Communication_p), Packet_p->Communication_p->Outbound_p, Packet_p); +} + +/* + * Function for Timer setting. + * + * @param [in] Packet_p Pointer to the R15 packet meta data. + * @param [in] InputData_p Pointer to the input parameters with settings. + * @param [in] Communication_p Communication module context. + * + * @return none. + */ +static Timer_t *TimerSet(PacketMeta_t *Packet_p, const SendData_LP_t *const InputData_p, Communication_t *Communication_p) +{ + Timer_t *Timer_p = NULL; + + if (InputData_p->Time > 0) { + Timer_p = (Timer_t *)malloc(sizeof(Timer_t)); + + if (NULL == Timer_p) { + return NULL; + } + + /* timer data */ + Timer_p->Time = InputData_p->Time; + Timer_p->PeriodicalTime = 0; + Timer_p->HandleFunction_p = (HandleFunction_t)(InputData_p->TimerCallBackFn_p); + Timer_p->Data_p = (void *)Packet_p; + Timer_p->Param_p = (void *)Communication_p; + } + + return Timer_p; +} +/** @} */ +/** @} */ +/** @} */ diff --git a/lcmodule/source/cnh1605204_ldr_transport_layer/source/z_transport.c b/lcmodule/source/cnh1605204_ldr_transport_layer/source/z_transport.c new file mode 100644 index 0000000..578e176 --- /dev/null +++ b/lcmodule/source/cnh1605204_ldr_transport_layer/source/z_transport.c @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (C) ST-Ericsson SA 2011 + * License terms: 3-clause BSD license + ******************************************************************************/ +/** + * @addtogroup ldr_communication_serv + * @{ + * @addtogroup z_family + * @{ + * @addtogroup ldr_transport_layer + * @{ + */ + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include <stdlib.h> +#include <string.h> + +#include "t_basicdefinitions.h" +#include "r_debug.h" +#include "r_z_transport.h" +#include "r_z_network.h" +#include "r_communication_service.h" +#include "r_z_protocol.h" + +/******************************************************************************* + * Declaration of file local functions + ******************************************************************************/ +static ErrorCode_e Z_Process(Communication_t *Communication_p); + +/******************************************************************************* + * File scope types, constants and variables + ******************************************************************************/ + +/******************************************************************************* + * Definition of external functions + ******************************************************************************/ + +/* + * Initializes the transport layer for Z protocol family. + * + * @param [in] Communication_p Communication module context. + * + * @retval E_SUCCESS After successful execution. + * @retval E_FAILED_TO_INIT_TL unsuccessful initialization. + * @retval E_ALLOCATE_FAILED failed to allocate memory space. + */ +ErrorCode_e Z_Transport_Initialize(const Communication_t *const Communication_p) +{ + return E_SUCCESS; +} + +/* + * Shut Down the transport layer for Z protocol family. + * + * @param [in] Communication_p Communication module context. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e Z_Transport_Shutdown(const Communication_t *const Communication_p) +{ + return E_SUCCESS; +} + +/* + * Handles all registered TL processes for Z protocol family. + * + * @param [in] Communication_p Communication module context. + * + * @retval E_SUCCESS After successful execution. + */ +ErrorCode_e Z_Transport_Poll(Communication_t *Communication_p) +{ + return Z_Process(Communication_p); +} + + +/* + * Function for sending packet in Z protocol family. + * + * @param [in] Communication_p Communication module context. + * @param [in] InputData_p Pointer to the input data. + * + * @retval E_SUCCESS After successful execution. + * @retval E_FAILED_TO_ALLOCATE_COMM_BUFFER Failed to allocate communication + * buffer. + */ +ErrorCode_e Z_Transport_Send(Communication_t *Communication_p, void *InputDataIn_p) +{ + Z_SendingContent_t SendingContent; + + SendingContent.Size = *((uint8 *)InputDataIn_p); + SendingContent.Data_p = (uint8 *)InputDataIn_p + 1; + + return Z_Network_TransmiterHandler(Communication_p, &SendingContent); +} + +/******************************************************************************* + * Definition of internal functions + ******************************************************************************/ +/* + * Handles all registered TL processes for Z protocol family. + * + * @param [in] Communication_p Communication module context. + * + * @retval E_SUCCESS After successful execution. + */ +static ErrorCode_e Z_Process(Communication_t *Communication_p) +{ + ErrorCode_e ReturnValue = E_SUCCESS; + + Z_Network_ReceiverHandler(Communication_p); + + return ReturnValue; +} + +/** @} */ +/** @} */ +/** @} */ |