You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
404 lines
13 KiB
404 lines
13 KiB
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2018 ST Microelectronics S.A.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
#ifndef _T1PROTOCOL_H_
|
|
#define _T1PROTOCOL_H_
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include "SpiLayerInterface.h"
|
|
#include "StEseApi.h"
|
|
#include "utils-lib/Tpdu.h"
|
|
|
|
// Recovery states
|
|
#define RECOVERY_STATUS_OK 0
|
|
#define RECOVERY_STATUS_RESEND_1 1
|
|
#define RECOVERY_STATUS_RESEND_2 2
|
|
#define RECOVERY_STATUS_RESYNC_1 3
|
|
#define RECOVERY_STATUS_RESYNC_2 4
|
|
#define RECOVERY_STATUS_RESYNC_3 5
|
|
#define RECOVERY_STATUS_WARM_RESET 6
|
|
#define RECOVERY_STATUS_KO 7
|
|
|
|
// Apdu modes
|
|
#define APDU_PART_IS_LAST true
|
|
#define APDU_PART_IS_NOT_LAST false
|
|
|
|
// SBlock types
|
|
#define SBLOCK_WTX_REQUEST_MASK 0b11000011
|
|
#define SBLOCK_WTX_RESPONSE_MASK 0b11100011
|
|
#define SBLOCK_IFS_REQUEST_MASK 0b11000001
|
|
#define SBLOCK_IFS_RESPONSE_MASK 0b11100001
|
|
#define SBLOCK_ABORT_REQUEST_MASK 0b11000010
|
|
#define SBLOCK_ABORT_RESPONSE_MASK 0b11100010
|
|
#define SBLOCK_RESYNCH_REQUEST_MASK 0b11000000
|
|
#define SBLOCK_RESYNCH_RESPONSE_MASK 0b11100000
|
|
#define SBLOCK_SWRESET_REQUEST_MASK 0b11001111
|
|
#define SBLOCK_SWRESET_RESPONSE_MASK 0b11101111
|
|
|
|
// IBlock parameters
|
|
#define IBLOCK_M_BIT_MASK 0b00100000
|
|
#define IBLOCK_NS_BIT_MASK 0b01000000
|
|
|
|
#define DEFAULT_NBWT 1
|
|
|
|
// Global variables
|
|
// uint8_t SEQ_NUM_MASTER;
|
|
// uint8_t SEQ_NUM_SLAVE;
|
|
// bool firstTransmission;
|
|
// uint8_t recoveryStatus;
|
|
// bool aborted;
|
|
// uint8_t IFSD;
|
|
|
|
typedef enum {
|
|
Idle = 0,
|
|
I_block,
|
|
R_ACK,
|
|
R_CRC_Error,
|
|
R_Other_Error,
|
|
S_Resync_REQ,
|
|
S_Resync_RES,
|
|
S_IFS_REQ,
|
|
S_IFS_RES,
|
|
S_WTX_RES,
|
|
S_SWReset_REQ
|
|
} T1TProtocol_TransceiveState;
|
|
/**
|
|
* Form a valid pcb according to the Tpdu type, subtype, master sequence number,
|
|
* slave sequence number and isLast.
|
|
*
|
|
* @param type The Tpdu type (IBlock, RBlock or SBlock).
|
|
* @param subtype The different subtype options when using RBlock. Error free,
|
|
* checksum error or other errors.
|
|
* @param numSeqMaster Master sequence number.
|
|
* @param numseqSlave Slave sequence number.
|
|
* @param isLast Indicate if there are more tpdus to send within the same APDU.
|
|
*
|
|
* @return pcb The value of the pcb computed.
|
|
*/
|
|
uint8_t T1protocol_getValidPcb(TpduType type, RBlockType subtype,
|
|
uint8_t numSeqMaster, uint8_t numseqSlave,
|
|
bool isLast);
|
|
|
|
/**
|
|
* Check if the checksum of a given tpdu is well formed.
|
|
*
|
|
* @param tpdu Tpdu to check.
|
|
*
|
|
* @return 0 If checksum is ok, -1 otherwise.
|
|
*/
|
|
int T1protocol_checkResponseTpduChecksum(Tpdu *tpdu);
|
|
|
|
/**
|
|
* Check if the pcb of a given tpdu is valid.
|
|
*
|
|
* @param tpdu Tpdu to check.
|
|
*
|
|
* @return 0 If checksum is ok, -1 otherwise.
|
|
*/
|
|
int T1protocol_checkResponsePcbConsistency(Tpdu *tpdu);
|
|
|
|
/**
|
|
* Check if the length field of a given tpdu is valid.
|
|
*
|
|
* @param tpdu Tpdu to check.
|
|
*
|
|
* @return 0 If checksum is ok, -1 otherwise.
|
|
*/
|
|
int T1protocol_checkResponseLenConsistency(Tpdu *tpdu);
|
|
|
|
/**
|
|
* Check if the sequence number of a given tpdu is valid.
|
|
*
|
|
* @param tpdu Tpdu to check.
|
|
*
|
|
* @return 0 If checksum is ok, -1 otherwise.
|
|
*/
|
|
int T1protocol_checkResponseSeqNumberConsistency(Tpdu *tpdu);
|
|
|
|
/**
|
|
* Check if an SBlock response was received after having transmitted a SBlock
|
|
* request.
|
|
*
|
|
* @param lastCmdTpduSent Last Tpdu sent.
|
|
* @param lastRespTpduReceived Response received.
|
|
*
|
|
* @return 0 If checksum is ok, -1 otherwise.
|
|
*/
|
|
int T1protocol_checkSBlockResponseConsistency(Tpdu *lastCmdTpduSent,
|
|
Tpdu *lastRespTpduReceived);
|
|
|
|
/**
|
|
* Check if the response TPDU is consistent (check the checksum, check if the
|
|
* pcb is valid and the expected one and check the len consistency).
|
|
*
|
|
* @param lastCmdTpduSent Last Tpdu sent, could be different than the
|
|
* originalCmdTpdu if there was retransmissions request or SBlocks.
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
*
|
|
* @return 0 If consistency is ok, -1 otherwise.
|
|
*/
|
|
int T1protocol_checkTpduConsistency(Tpdu *lastCmdTpduSent,
|
|
Tpdu *lastRespTpduReceived);
|
|
|
|
/**
|
|
* Set the sequence numbers to it's initial values.
|
|
*/
|
|
void T1protocol_resetSequenceNumbers();
|
|
|
|
/**
|
|
* Update the master sequence number. Increase the value, taking into account is
|
|
* module 2 type.
|
|
*/
|
|
void T1protocol_updateMasterSequenceNumber();
|
|
|
|
/**
|
|
* Update the slave sequence number. Increase the value, taking into account is
|
|
* module 2 type.
|
|
*/
|
|
void T1protocol_updateSlaveSequenceNumber();
|
|
|
|
/**
|
|
* Process the last IBlock received from the slave.
|
|
*
|
|
* @param originalCmdTpdu Original Tpdu sent.
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
*
|
|
* @return 0 If all went is ok, -1 otherwise.
|
|
*/
|
|
int T1protocol_processIBlock(Tpdu* originalCmdTpdu, Tpdu* lastRespTpduReceived);
|
|
|
|
/**
|
|
* Process the last RBlock received from the slave.
|
|
*
|
|
* @param originalCmdTpdu Original Tpdu sent.
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
*
|
|
*/
|
|
void T1protocol_processRBlock(Tpdu *originalCmdTpdu,
|
|
Tpdu *lastRespTpduReceived);
|
|
|
|
/**
|
|
* Process the last RBlock received from the slave.
|
|
*
|
|
* @param rack if 1, send a ack frame, nack otherwise.
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
*
|
|
* @return -1 if the retransmission needed fails, 0 if no more retransmission
|
|
* were needed and 1 if extra retransmission success.
|
|
*/
|
|
int T1protocol_sendRBlock(int rack, Tpdu *lastRespTpduReceived);
|
|
|
|
/**
|
|
* Form a SBlock response according to a given SBlock Request.
|
|
*
|
|
* @param responseTpdu A valid SBlock response according to the SBlock request
|
|
* in the requestTpdu param.
|
|
* @param requestTpdu The Sblock request received from the eSE to process.
|
|
*
|
|
* @return 0 If all went is ok, -1 otherwise.
|
|
*/
|
|
int T1protocol_formSblockResponse(Tpdu *responseTpdu, Tpdu *requestTpdu);
|
|
|
|
/**
|
|
* Process the last SBlock received from the slave.
|
|
*
|
|
* @param originalCmdTpdu Original Tpdu sent.
|
|
* @param lastCmdTpduSent Last Tpdu sent, could be different than the
|
|
* originalCmdTpdu if there was retransmissions request or SBlocks.
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
*
|
|
* @return -1 if the extra retransmission needed fails or 1 if extra
|
|
* retransmission success.
|
|
*/
|
|
int T1protocol_processSBlock(Tpdu *originalCmdTpdu, Tpdu *lastCmdTpduSent,
|
|
Tpdu *lastRespTpduReceived);
|
|
|
|
/**
|
|
* Check if the sequence number of the response TPDU is the expected one.
|
|
*
|
|
* @param originalTpdu The original tpdu sent.
|
|
* @param respTpdu The last response received from the slave.
|
|
*
|
|
* @return true If sequence number is ok, false otherwise.
|
|
*/
|
|
bool T1protocol_isSequenceNumberOk(Tpdu *originalTpdu, Tpdu *respTpdu);
|
|
|
|
/**
|
|
* Updates the recovery state to the following step.
|
|
*/
|
|
void T1protocol_updateRecoveryStatus();
|
|
|
|
/**
|
|
* Copy the data in the response Tpdu into the respApduBuffer.
|
|
*
|
|
* @param respTpdu Response tpdu where the data is stored.
|
|
* @param respApduBuffer Apdu buffer where to store the data received in the
|
|
* response Tpdu.
|
|
*
|
|
* @return The amount of data bytes saved into the apdu buffer.
|
|
*/
|
|
uint8_t T1protocol_setRespApduData(Tpdu *respTpdu, uint8_t *respApduBuffer);
|
|
|
|
/**
|
|
* If the eSE send a S(WTX request), acknowledge it by sending
|
|
* a S(WTX response)
|
|
*
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
*
|
|
* @return bytesRead if data was read, 0 if timeout expired with
|
|
* no response, -1 otherwise
|
|
*/
|
|
int T1protocol_doWTXResponse(Tpdu *lastRespTpduReceived);
|
|
|
|
/**
|
|
* The first thing to do in the recovery mechanism is to ask for a
|
|
* retransmission.
|
|
*
|
|
* @param lastCmdTpduSent Last Tpdu sent, could be different than the
|
|
* originalCmdTpdu if there was retransmissions request or SBlocks.
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
* @param bytesRead If a retransmission occurs, this field contains the amout of
|
|
* bytes read from the slave in the new transaction.
|
|
*
|
|
* @return 0 if everything went fine, -1 if something failed.
|
|
*/
|
|
int T1protocol_doResendRequest(Tpdu *lastCmdTpduSent,
|
|
Tpdu *lastRespTpduReceived, int *bytesRead);
|
|
|
|
/**
|
|
* The second thing to do in the recovery mechanism if the resend fails
|
|
* is to perform a Resync.
|
|
*
|
|
* @param lastCmdTpduSent Last Tpdu sent, could be different than the
|
|
* originalCmdTpdu if there was retransmissions request or SBlocks.
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
* @param bytesRead If a retransmission occurs, this field contains the amout of
|
|
* bytes read from the slave in the new transaction.
|
|
*
|
|
* @return 0 if everything went fine, -1 if something failed.
|
|
*/
|
|
int T1protocol_doResyncRequest(Tpdu *lastRespTpduReceived);
|
|
|
|
/**
|
|
* Implements the recovery mechanism when a non-consistent TPDU has been
|
|
* received or no response has been received before the timeout.
|
|
*
|
|
* @param lastCmdTpduSent Last Tpdu sent, could be different than the
|
|
* originalCmdTpdu if there was retransmissions request or SBlocks.
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
* @param bytesRead If a retransmission occurs, this field contains the amout of
|
|
* bytes read from the slave in the new transaction.
|
|
*
|
|
* @return 0 if everything went fine,
|
|
* -1 if something failed, or
|
|
* RC_WARM_RESET_REQUIERD if a warm reset needs to be performed.
|
|
* TODO: If a warm reset needs to be performed, the service will die
|
|
* and the user will need do the reset manually, as Power Manager is not
|
|
* yet implemented.
|
|
*/
|
|
int T1protocol_doRecovery();
|
|
|
|
/**
|
|
* Send a soft reset (S-Block)
|
|
*
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
*
|
|
* @return 0 if everything went fine, -1 if an error occurred.
|
|
*/
|
|
int T1protocol_doSoftReset(Tpdu *lastRespTpduReceived);
|
|
|
|
/**
|
|
* Send IFS request(S-Block)
|
|
*
|
|
* @param None.
|
|
*
|
|
* @return 0 if everything went fine, -1 if an error occurred.
|
|
*/
|
|
int T1protocol_doRequestIFS(Tpdu* lastRespTpduReceived);
|
|
|
|
/**
|
|
* Handles any TPDU response iteratively.
|
|
*
|
|
* @param originalCmdTpdu Original Tpdu sent.
|
|
* @param lastCmdTpduSent Last Tpdu sent, could be different than the
|
|
* originalCmdTpdu if there was retransmissions request or SBlocks.
|
|
* @param lastRespTpduReceived Last response received from the slave.
|
|
* @param bytesRead If a retransmission occurs, this field contains the amout of
|
|
* bytes read from the slave in the new transaction.
|
|
*
|
|
* @return 0 if everything went fine, -1 if an error occurred.
|
|
*/
|
|
int T1protocol_handleTpduResponse(Tpdu *originalCmdTpdu, Tpdu *lastCmdTpduSent,
|
|
Tpdu *lastRespTpduReceived, int *bytesRead);
|
|
|
|
/**
|
|
* Form a valid Tpdu to send according to the if we need to send
|
|
* an IBlock or a RBlock (for chained response from the slave).
|
|
*
|
|
* @param cmdApduPart Data to sent within an IBlock.
|
|
* @param cmdLength Amount of data to sent.
|
|
* @param isLast Flag indicating if there are more data to send.
|
|
* @param cmdTpdu Resulting Tpdu.
|
|
*
|
|
* @return 0 if everything went fine, -1 if something failed.
|
|
*/
|
|
int T1protocol_formCommandTpduToSend(uint8_t *cmdApduPart, uint8_t cmdLength,
|
|
bool isLast, Tpdu *cmdTpdu);
|
|
|
|
/**
|
|
* Initializes the T1 Protocol.
|
|
*
|
|
* @return 0 if initialization was ok, -1 otherwise.
|
|
*/
|
|
int T1protocol_init(SpiDriver_config_t *tSpiDriver);
|
|
|
|
/**
|
|
* This method is used to send and/or receive an APDU part. There are 3 ways of
|
|
* calling it:
|
|
* 1. transcieveApduPart(&cmdApduPart, cmdLength, APDU_PART_IS_NOT_LAST, null,
|
|
* null): will send an APDU part and expect no response.
|
|
* 2. transcieveApduPart(&cmdApduPart, cmdLength, APDU_PART_IS_LAST,
|
|
* &respApduPart, &respLength): will send an APDU part and get a response
|
|
* part.
|
|
* 3. transcieveApduPart(null, null, null, &respApduPart, &respLength): sends no
|
|
* APDU part and gets a response part.
|
|
*
|
|
* It will for and send the required TPDU, receive the response and handle it.
|
|
*
|
|
* @param cmdApduPart The cmdApdu part that shall be sent (or null).
|
|
* @param cmdLength The length of the cmdApduPart to be sent (or null).
|
|
* @param isLast Either APDU_PART_IS_NOT_LAST or APDU_PART_IS_LAST (or null).
|
|
* @param pRsp Structure to the response buffer and length.
|
|
* (or null).
|
|
*
|
|
* @return If no response is expected:
|
|
* - 0 if everything was ok
|
|
* - -1 if an error occurred
|
|
* If response is expected:
|
|
* - 0 if it is the last response part
|
|
* - 1 if there are more response parts
|
|
* - -1 if an error occurred.
|
|
*/
|
|
int T1protocol_transcieveApduPart(uint8_t* cmdApduPart, uint8_t cmdLength,
|
|
bool isLast, StEse_data* pRsp,
|
|
T1TProtocol_TransceiveState Block_type);
|
|
|
|
#endif /* _T1PROTOCOL_H_ */
|