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