#ifndef _7816_3_T1_T1_H_
|
#define _7816_3_T1_T1_H_
|
|
#include <stdbool.h>
|
#include <stdint.h>
|
#include <stdlib.h>
|
|
#include "se_common.h"
|
|
#define CRC_PRESET 0xFFFF
|
#define CRC_POLYNOMIAL 0x8408
|
|
#define T1_DEFAULT_IFS 0xFE
|
|
// Node address device to card
|
#define NAD_D2C 0x5A
|
// Node address card to device
|
#define NAD_C2DT 0xA5
|
|
// T1 prologue field length and offset [start]
|
#define T1_HEADER_LEN 0x03
|
// ext frame's length is 2 bytes, refer to "GPC APDU Transport over SPI / I2C Version 1.0"
|
// The LEN and CRC fields shall have their Most Significant Byte sent first (i.e. big-endian order).
|
#define T1_EXT_HEADER_LEN 0x04
|
// T1 protocol frame LRC length is 1 byte
|
#define T1_LRC_LEN 0x01
|
// T1 protocol frame CRC length is 2 bytes
|
#define T1_CRC_LEN 0x02
|
|
#define T1_NAD_OFFSET 0x00
|
#define T1_PCB_OFFSET 0x01
|
#define T1_FRAME_LEN_OFFSET 0x02
|
#define T1_FRAME_LEN_OFFSET2 0x03
|
// T1 prologue field length and offset [end]
|
|
// T1 flags bit for masking [start]
|
#define T1_CHAINING_MASK 0x20
|
#define T1_S_BLOCK_REQ_MASK 0xC0
|
#define T1_S_BLOCK_RSP_MASK 0xE0
|
#define T1_I_BLOCK_SEQ_NO_MASK 0x40
|
#define T1_R_BLOCK_SEQ_NO_MASK 0x10
|
|
#define T1_S_BLOCK_SUB_TYPE_MASK 0x3F
|
|
// reference to ATR definition field: capbilities
|
#define T1_EXT_HEADER_LEN_MASK 0x04
|
|
typedef enum
|
{
|
LRC = 0x00,
|
CRC = 0x01,
|
CHK_INVALID,
|
} chk_code_types;
|
|
/* atr info: ISO7816 ATR Information bytes
|
* This structure holds ATR information bytes, contains ATR length.
|
*/
|
typedef struct
|
{
|
uint8_t len; // ATR length in bytes
|
uint8_t vendor_ID[5]; // Vendor_ID according to ISO7816-5
|
uint8_t dll_IC; // Data Link Layer - Interface Character
|
uint8_t bgt[2]; // Minimum guard time in milliseconds for
|
// T=1 blocks sent in opposite directions.
|
|
uint8_t bwt[2]; // Maximum allowed command processing
|
// time in milliseconds before card has sent either
|
// command response or S(WTX) requesting processing time extension
|
|
uint8_t max_freq[2]; // Max supported clock frequency in kHz
|
uint8_t checksum; // Checksum (0 = LRC / 1 = CRC)
|
uint8_t default_IFSC; // Default IFS size--Recommended value is 0x0102(258), APDU(256) + sw1sw2(2)
|
|
uint8_t num_channels; // Number of logical connections supported
|
uint8_t max_IFSC[2]; // Maximum size of IFS supported
|
uint8_t capbilities[2]; // Bitmap to indicate various features supported by SE
|
// Bit-1: SE Data Available Line supported.
|
// Bit-2: SE Data available polarity. 1 - Data available GPIO will be pulled HIGH when SE response is ready
|
// Bit 3: SE chip reset S-blk command supported
|
// Bit-4: Extended frame length feature supported
|
// Bit-5: Support for more than one logical channel
|
// Bit 6 to 16: Reserved for future use
|
} atr_info;
|
|
typedef struct
|
{
|
uint8_t lsb : 1; // PCB: lsb
|
uint8_t bit2 : 1; // PCB: bit2
|
uint8_t bit3 : 1; // PCB: bit3
|
uint8_t bit4 : 1; // PCB: bit4
|
uint8_t bit5 : 1; // PCB: bit5
|
uint8_t bit6 : 1; // PCB: bit6
|
uint8_t bit7 : 1; // PCB: bit7
|
uint8_t msb : 1; // PCB: msb
|
} T1_pcb_bits;
|
|
/** T1 Frame types **/
|
typedef enum
|
{
|
FRAME_TYPE_INVALID_MIN, // Frame type: INVALID
|
IFRAME, // Frame type: I-frame
|
RFRAME, // Frame type: R-frame
|
SFRAME, // Frame type: S-frame
|
FRAME_TYPE_INVALID_MAX, // Frame type: INVALID
|
} T1_frame_types;
|
|
/** T1 S-Frame sub-types **/
|
typedef enum
|
{
|
RESYNC_REQ = 0x00, // Re-synchronisation request between host and ESE
|
RESYNC_RSP = 0x20, // Re-synchronisation response between host and ESE
|
IFS_REQ = 0x01, // IFSC size request
|
IFS_RSP = 0x21, // IFSC size response
|
ABORT_REQ = 0x02, // Abort request
|
ABORT_RSP = 0x22, // Abort response
|
WTX_REQ = 0x03, // WTX request
|
WTX_RSP = 0x23, // WTX response
|
CIP_REQ = 0x04, // Interface reset request(Communication Interface Parameters request)
|
CIP_RSP = 0x24, // Interface reset response(Communication Interface Parameters response)
|
PROP_END_APDU_REQ = 0x05, // Proprietary Enf of APDU request
|
PROP_END_APDU_RSP = 0x25, // Proprietary Enf of APDU response
|
HARD_RESET_REQ = 0x06, // Chip reset request
|
HARD_RESET_RSP = 0x26, // Chip reset request
|
ATR_REQ = 0x07, // ATR request
|
ATR_RSP = 0x27, // ATR response
|
SFRAME_TYPE_INVALID, // Invalid request
|
} Sframe_types;
|
|
/** T1 R-Frame sub-types **/
|
typedef enum
|
{
|
RACK = 0x00, // R-frame Acknowledgement frame indicator, an error-free acknowledgement
|
RNACK_PARITY_ERROR = 0x01, // R-frame Negative-Acknowledgement frame indicator,
|
// a redundancy code error or a character parity error.
|
RNACK_OTHER_ERROR = 0x02, // R-frame Negative-Acknowledgement frame indicator, other errors.
|
RNACK_INVALID_ERROR = 0xFF, // Invalid R-block request
|
} Rframe_types;
|
|
typedef enum
|
{
|
STATE_IDEL = 0,
|
I_BLK,
|
R_ACK,
|
R_PARITY_ERR,
|
R_OTHER_ERR,
|
S_RESYNC_REQ,
|
S_IFS_REQ,
|
S_IFS_RSP,
|
S_ABORT_REQ,
|
S_ABORT_RSP,
|
S_WTX_REQ,
|
S_WTX_RSP,
|
S_CIP_REQ,
|
S_PROP_END_APDU_REQ,
|
S_ATR_REQ,
|
} T1_transmit_receive_state;
|
|
/** T1 protocol param **/
|
typedef struct
|
{
|
bool is_device_chaining;
|
bool is_card_chaining;
|
|
uint8_t recovery_cnt;
|
|
uint8_t resync_CIP_req_cnt;
|
|
uint8_t blk_retry_cnt;
|
|
uint8_t wtx_cnt;
|
|
uint8_t wtx_info;
|
|
T1_frame_types tx_frame_type;
|
Sframe_types tx_sub_Sframe_type;
|
Rframe_types tx_sub_Rframe_type;
|
|
// for recovery
|
T1_frame_types last_rx_frame_type;
|
Sframe_types last_rx_sub_Sframe_type;
|
Rframe_types last_rx_sub_Rframe_type;
|
T1_pcb_bits last_rx_pcb_bits;
|
|
// only I-block used
|
uint8_t *p_data_tx;
|
uint16_t tx_len;
|
uint8_t *p_data_tx_part;
|
uint16_t tx_len_part;
|
uint16_t tx_data_offset;
|
// end only I-block used
|
} T1_params;
|
|
ESESTATUS t1_transmit_receive_apdu(uint8_t *p_cmd_apdu, uint16_t cmd_len);
|
ESESTATUS t1_CIP_req(void);
|
ESESTATUS t1_ATR_req(void);
|
ESESTATUS t1_IFSD_req(void);
|
ESESTATUS t1_prop_end_apdu_req(void);
|
ESESTATUS t1_receive_data_and_get(uint8_t **pp_Data, uint16_t *data_len);
|
|
extern uint32_t g_recv_total_len;
|
extern uint8_t gp_data_rx[270];
|
extern atr_info g_atr;
|
|
ESESTATUS response_process(void);
|
ESESTATUS Transmit_receive_process(void);
|
ESESTATUS t1_send_Sframe(void);
|
ESESTATUS t1_send_Iframe(void);
|
ESESTATUS t1_send_Rframe(void);
|
ESESTATUS t1_chk_epilogue(uint8_t *p_data, uint16_t offset, uint16_t len);
|
ESESTATUS t1_decode_frame(uint16_t data_len);
|
uint8_t get_header_len(bool contains_epilogue);
|
ESESTATUS init_Iframe_from_cmd_apdu(uint8_t *p_cmd_apdu, uint16_t cmd_len);
|
void deinit_Iframe_from_cmd_apdu(void);
|
ESESTATUS do_T1_recovery_at_undecode(void);
|
ESESTATUS t1_transmit_only_apdu(uint8_t *p_cmd_apdu, uint16_t cmd_len);
|
ESESTATUS t1_receive_only_apdu(void);
|
|
#endif /* _T1PROTOCOL_H_ */
|