summaryrefslogtreecommitdiff
path: root/lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_protocol.c')
-rw-r--r--lcmodule/source/cnh1605204_ldr_transport_layer/source/a2_protocol.c309
1 files changed, 309 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);
+}
+
+/** @} */
+/** @} */
+/** @} */