| /****************************************************************************** |
| * |
| * Copyright 2018-2021 NXP |
| * |
| * 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. |
| * |
| ******************************************************************************/ |
| #define LOG_TAG "NxpEseHal" |
| #include <log/log.h> |
| #include <phNxpEseProto7816_3.h> |
| |
| /** |
| * \addtogroup ISO7816-3_protocol_lib |
| * |
| * @{ */ |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This function is used to reset the 7816 protocol stack instance |
| * |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_ResetProtoParams(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called send the data to ESE |
| *\param[in] data_len - data len |
| *\param[in] p_data -address to raw data |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_SendRawFrame(uint32_t data_len, |
| uint8_t* p_data); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called read the data from the ESE |
| *\param[in] data_len - data len |
| *\param[in] pp_data -address to raw data |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_GetRawFrame(uint32_t* data_len, |
| uint8_t** pp_data); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called compute the LRC |
| *\param[in] p_buff - raw data |
| *\param[in] offset -address to raw data |
| *\param[in] length - length of data. |
| *\retval LRC value. |
| * |
| */ |
| static uint8_t phNxpEseProto7816_ComputeLRC(unsigned char* p_buff, |
| uint32_t offset, uint32_t length); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called compute and compare the |
| * received LRC of the received data |
| *\param[in] data_len - raw data |
| *\param[in] p_data -address to raw data |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_CheckLRC(uint32_t data_len, uint8_t* p_data); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called to send S-frame with all |
| * updated 7816-3 headers |
| *\param[in] sFrameData -S frame APDU |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_SendSFrame(sFrameInfo_t sFrameData); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called to send I-frame with all |
| * updated 7816-3 headers |
| *\param[in] iFrameData -I frame APDU |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_SendIframe(iFrameInfo_t iFrameData); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called to send R-frame with all |
| *updated 7816-3 headers |
| *\param[in] rFrameType -R frame APDU |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_sendRframe(rFrameTypes_t rFrameType); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called to set the context for first |
| *I-frame. Not applicable for the first I-frame of the transceive |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_SetFirstIframeContxt(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called to set the context for next |
| *I-frame. Not applicable for the first I-frame of the transceive |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_SetNextIframeContxt(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called to push I-frame data to internal |
| *structure. \param[in] p_data -raw data buffer \param[in] data_len -data |
| *length |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_SaveIframeData(uint8_t* p_data, |
| uint32_t data_len); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called to do reset the recovery |
| *pareameters |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_ResetRecovery(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is called when 7816-3 stack failed to |
| *recover after PH_PROTO_7816_FRAME_RETRY_COUNT, and the interface has |
| *to be recovered |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_RecoverySteps(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is used to |
| * 1. Identify the received frame |
| * 2. If the received frame is I-frame with expected sequence |
| number, store it or else send R-NACK |
| 3. If the received frame is R-frame, |
| 3.1 R-ACK with expected seq. number: Send the next |
| chained I-frame |
| 3.2 R-ACK with different sequence number: Send the R-Nack |
| 3.3 R-NACK: Re-send the last frame |
| 4. If the received frame is S-frame, send back the correct |
| S-frame response. |
| *\param[in] p_data -address of data. |
| *\param[in] data_len -length of the frame |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_DecodeFrame(uint8_t* p_data, |
| uint32_t data_len); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is used to |
| * 1. Check the LRC |
| * 2. Initiate decoding of received frame of data. |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_ProcessResponse(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is used to |
| * 1. Send the raw data received from application after |
| *computing LRC |
| * 2. Receive the response data from ESE, decode, process |
| *and |
| * store the data. |
| * |
| */ |
| static ESESTATUS TransceiveProcess(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is used to |
| * 1. Send propreitary S-Frame command for resynch |
| *T=1 sequence at client |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_RSync(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This function is used to reset the 7816 protocol stack |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_ResetProtoParams(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This function is used to send the spi hard reset command |
| * |
| */ |
| static ESESTATUS phNxpEseProto7816_HardReset(void); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is to decode the secure timer. |
| * value from the payload |
| *\param[in] frameOffset -To get the L of TLV |
| *\param[in] secureTimer -V of TLV: Retrieve each byte(4 byte) and push it |
| *to get the secure timer value (unsigned long) \param[in] p_data -pointer to |
| *data. |
| * |
| */ |
| static void phNxpEseProto7816_DecodeSecureTimer(uint8_t* frameOffset, |
| unsigned int* secureTimer, |
| uint8_t* p_data); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is to decode S-frame payload. |
| *\param[in] p_data -Raw Data IFS. |
| * |
| */ |
| static void phNxpEseProto7816_DecodeSFrameIFSData(uint8_t* p_data); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is to decode S-frame (ATR) payload. |
| *\param[in] p_data -ATR TLV. |
| * |
| */ |
| static void phNxpEseProto7816_DecodeSFrameATRData(uint8_t* p_data); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is to decode S-frame (secure timer TLV) |
| *payload. \param[in] p_data -raw data - secure timer TLV. |
| * |
| */ |
| static void phNxpEseProto7816_DecodeSFrameSecureTimerData(uint8_t* p_data); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function is to notify either WTX_ONGOING ot |
| *WTX_END \param[in] state - Either WTX_ONGOING/WTX_END |
| * |
| */ |
| static void phNxpEseProto7816_CheckAndNotifyWtx(phNxpEse_wtxState state); |
| |
| /** |
| * \ingroup ISO7816-3_protocol_lib |
| * \brief This internal function to check Last sent frame is S-Frame |
| * request and if received block is not S-Frame response |
| * re-send Last S-frame request |
| */ |
| static bool phNxpEseProto7816_ResendLastSFrameReq(void); |
| /*! |
| * \brief 7816_3 protocol stack parameter variable instance |
| */ |
| static phNxpEseProto7816_t phNxpEseProto7816_3_Var; |
| |
| /*! |
| * \brief 7816_3 protocol stack instance - pointer variable |
| */ |
| static phNxpEseProto7816_t phNxpEseProto7816_ptr[MAX_END_POINTS]; |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_SendRawFrame |
| * |
| * Description This internal function is called send the data to ESE |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_SendRawFrame(uint32_t data_len, |
| uint8_t* p_data) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| status = phNxpEse_WriteFrame(data_len, p_data); |
| if (ESESTATUS_SUCCESS != status) { |
| ALOGE("%s Error phNxpEse_WriteFrame\n", __FUNCTION__); |
| } else { |
| ALOGD_IF(ese_debug_enabled, "%s phNxpEse_WriteFrame Success \n", |
| __FUNCTION__); |
| } |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_GetRawFrame |
| * |
| * Description This internal function is called read the data from the ESE |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_GetRawFrame(uint32_t* data_len, |
| uint8_t** pp_data) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| |
| status = phNxpEse_read(data_len, pp_data); |
| if (ESESTATUS_SUCCESS != status) { |
| ALOGE("%s phNxpEse_read failed , status : 0x%x", __FUNCTION__, status); |
| } |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_ComputeLRC |
| * |
| * Description This internal function is called compute the LRC |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static uint8_t phNxpEseProto7816_ComputeLRC(unsigned char* p_buff, |
| uint32_t offset, uint32_t length) { |
| uint32_t LRC = 0, i = 0; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| for (i = offset; i < length; i++) { |
| LRC = LRC ^ p_buff[i]; |
| } |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return (uint8_t)LRC; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_CheckLRC |
| * |
| * Description This internal function is called compute and compare the |
| * received LRC of the received data |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_CheckLRC(uint32_t data_len, |
| uint8_t* p_data) { |
| ESESTATUS status = ESESTATUS_SUCCESS; |
| uint8_t calc_crc = 0; |
| uint8_t recv_crc = 0; |
| ALOGD_IF(ese_debug_enabled, "Enter %s len %d", __FUNCTION__, data_len); |
| if (data_len > 0) { |
| recv_crc = p_data[data_len - 1]; |
| |
| /* calculate the CRC after excluding CRC */ |
| calc_crc = phNxpEseProto7816_ComputeLRC(p_data, 1, (data_len - 1)); |
| ALOGD_IF(ese_debug_enabled, "Received LRC:0x%x Calculated LRC:0x%x", |
| recv_crc, calc_crc); |
| if (recv_crc != calc_crc) { |
| status = ESESTATUS_FAILED; |
| ALOGE("%s LRC failed", __FUNCTION__); |
| } |
| } else { |
| status = ESESTATUS_FAILED; |
| ALOGE("%s LRC failed length = 0", __FUNCTION__); |
| } |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_SendSFrame |
| * |
| * Description This internal function is called to send S-frame with all |
| * updated 7816-3 headers |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_SendSFrame(sFrameInfo_t sFrameData) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| uint32_t frame_len = 0; |
| uint8_t* p_framebuff = NULL; |
| uint8_t pcb_byte = 0; |
| uint8_t lenIFS = 0; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| sFrameInfo_t sframeData = sFrameData; |
| /* This update is helpful in-case a R-NACK is transmitted from the MW */ |
| phNxpEseProto7816_3_Var.lastSentNonErrorframeType = SFRAME; |
| switch (sframeData.sFrameType) { |
| case RESYNCH_REQ: |
| frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); |
| p_framebuff = (uint8_t*)phNxpEse_memalloc(frame_len * sizeof(uint8_t)); |
| if (NULL == p_framebuff) { |
| return ESESTATUS_FAILED; |
| } |
| p_framebuff[2] = 0; |
| p_framebuff[3] = 0x00; |
| |
| pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ |
| pcb_byte |= PH_PROTO_7816_S_RESYNCH; |
| break; |
| case IFS_REQ: |
| frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); |
| lenIFS = 0; |
| if (IFSC_SIZE_SEND < phNxpEseProto7816_3_Var.currentIFSDSize) { |
| frame_len += 2; |
| lenIFS = 2; |
| } else { |
| frame_len += 1; |
| lenIFS = 1; |
| } |
| |
| p_framebuff = (uint8_t*)phNxpEse_memalloc(frame_len * sizeof(uint8_t)); |
| if (NULL == p_framebuff) { |
| return ESESTATUS_FAILED; |
| } |
| p_framebuff[2] = lenIFS; |
| if (2 == lenIFS) { |
| p_framebuff[3] = (phNxpEseProto7816_3_Var.currentIFSDSize >> 8); |
| p_framebuff[4] = |
| (phNxpEseProto7816_3_Var.currentIFSDSize & EXTENDED_FRAME_MARKER); |
| } else { |
| p_framebuff[3] = phNxpEseProto7816_3_Var.currentIFSDSize; |
| } |
| |
| pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ |
| pcb_byte |= IFS_REQ; |
| break; |
| case INTF_RESET_REQ: |
| frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); |
| p_framebuff = (uint8_t*)phNxpEse_memalloc(frame_len * sizeof(uint8_t)); |
| if (NULL == p_framebuff) { |
| return ESESTATUS_FAILED; |
| } |
| p_framebuff[2] = 0; |
| p_framebuff[3] = 0x00; |
| |
| pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ |
| pcb_byte |= PH_PROTO_7816_S_RESET; |
| break; |
| case PROP_END_APDU_REQ: |
| frame_len = |
| (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN + sframeData.len); |
| p_framebuff = (uint8_t*)phNxpEse_memalloc(frame_len * sizeof(uint8_t)); |
| if (NULL == p_framebuff) { |
| return ESESTATUS_FAILED; |
| } |
| p_framebuff[2] = sframeData.len; |
| if (!sframeData.len) |
| p_framebuff[3] = PH_PROTO_7816_VALUE_ZERO; |
| else |
| phNxpEse_memcpy(&(p_framebuff[3]), sframeData.p_data, sframeData.len); |
| pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ |
| pcb_byte |= PH_PROTO_7816_S_END_OF_APDU; |
| break; |
| case HARD_RESET_REQ: |
| frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); |
| p_framebuff = (uint8_t*)phNxpEse_memalloc(frame_len * sizeof(uint8_t)); |
| if (NULL == p_framebuff) { |
| return ESESTATUS_FAILED; |
| } |
| p_framebuff[2] = 0; |
| p_framebuff[3] = 0x00; |
| |
| pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ |
| pcb_byte |= PH_PROTO_7816_S_HRD_RST_CMD; |
| break; |
| case WTX_RSP: |
| frame_len = (PH_PROTO_7816_HEADER_LEN + 1 + PH_PROTO_7816_CRC_LEN); |
| p_framebuff = (uint8_t*)phNxpEse_memalloc(frame_len * sizeof(uint8_t)); |
| if (NULL == p_framebuff) { |
| return ESESTATUS_FAILED; |
| } |
| p_framebuff[2] = 0x01; |
| p_framebuff[3] = 0x01; |
| |
| pcb_byte |= PH_PROTO_7816_S_BLOCK_RSP; |
| pcb_byte |= PH_PROTO_7816_S_WTX; |
| break; |
| case ATR_REQ: |
| frame_len = (PH_PROTO_7816_HEADER_LEN + PH_PROTO_7816_CRC_LEN); |
| p_framebuff = (uint8_t*)phNxpEse_memalloc(frame_len * sizeof(uint8_t)); |
| if (NULL == p_framebuff) { |
| return ESESTATUS_FAILED; |
| } |
| p_framebuff[2] = 0; |
| p_framebuff[3] = 0x00; |
| |
| pcb_byte |= PH_PROTO_7816_S_BLOCK_REQ; /* PCB */ |
| pcb_byte |= ATR_REQ; |
| break; |
| default: |
| ALOGE("Invalid S-block"); |
| break; |
| } |
| if (NULL != p_framebuff) { |
| /* frame the packet */ |
| p_framebuff[0] = 0x00; /* NAD Byte */ |
| p_framebuff[1] = pcb_byte; /* PCB */ |
| |
| p_framebuff[frame_len - 1] = |
| phNxpEseProto7816_ComputeLRC(p_framebuff, 0, (frame_len - 1)); |
| ALOGD_IF(ese_debug_enabled, "S-Frame PCB: %x\n", p_framebuff[1]); |
| status = phNxpEseProto7816_SendRawFrame(frame_len, p_framebuff); |
| phNxpEse_free(p_framebuff); |
| /*After S-Frame Tx 1 ms sleep before Rx*/ |
| if ((GET_CHIP_OS_VERSION() != OS_VERSION_4_0) && |
| (sframeData.sFrameType != PROP_END_APDU_REQ)) { |
| phNxpEse_Sleep(1 * 1000); |
| } |
| } else { |
| ALOGE("Invalid S-block or malloc for s-block failed"); |
| } |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_sendRframe |
| * |
| * Description This internal function is called to send R-frame with all |
| * updated 7816-3 headers |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_sendRframe(rFrameTypes_t rFrameType) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| uint8_t recv_ack[4] = {0x00, 0x80, 0x00, 0x00}; |
| if (RNACK == rFrameType) /* R-NACK */ |
| { |
| recv_ack[1] = 0x82; |
| } else /* R-ACK*/ |
| { |
| /* This update is helpful in-case a R-NACK is transmitted from the MW */ |
| phNxpEseProto7816_3_Var.lastSentNonErrorframeType = RFRAME; |
| } |
| recv_ack[1] |= |
| ((phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo.seqNo ^ 1) |
| << 4); |
| ALOGD_IF(ese_debug_enabled, "%s recv_ack[1]:0x%x", __FUNCTION__, recv_ack[1]); |
| recv_ack[3] = |
| phNxpEseProto7816_ComputeLRC(recv_ack, 0x00, (sizeof(recv_ack) - 1)); |
| status = phNxpEseProto7816_SendRawFrame(sizeof(recv_ack), recv_ack); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_SendIframe |
| * |
| * Description This internal function is called to send I-frame with all |
| * updated 7816-3 headers |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_SendIframe(iFrameInfo_t iFrameData) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| uint32_t frame_len = 0; |
| uint8_t* p_framebuff = NULL; |
| uint8_t pcb_byte = 0; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| if (0 == iFrameData.sendDataLen) { |
| ALOGE("I frame Len is 0, INVALID"); |
| return ESESTATUS_FAILED; |
| } |
| /* This update is helpful in-case a R-NACK is transmitted from the MW */ |
| phNxpEseProto7816_3_Var.lastSentNonErrorframeType = IFRAME; |
| frame_len = (iFrameData.sendDataLen + PH_PROTO_7816_HEADER_LEN + |
| PH_PROTO_7816_CRC_LEN + 2); |
| |
| p_framebuff = (uint8_t*)phNxpEse_memalloc(frame_len * sizeof(uint8_t)); |
| if (NULL == p_framebuff) { |
| ALOGE("Heap allocation failed"); |
| return ESESTATUS_FAILED; |
| } |
| |
| /* frame the packet */ |
| p_framebuff[0] = 0x00; /* NAD Byte */ |
| |
| if (iFrameData.isChained) { |
| /* make B6 (M) bit high */ |
| pcb_byte |= PH_PROTO_7816_CHAINING; |
| } |
| |
| /* Update the send seq no */ |
| pcb_byte |= |
| (phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.seqNo << 6); |
| |
| /* store the pcb byte */ |
| p_framebuff[1] = pcb_byte; |
| if (iFrameData.sendDataLen > |
| IFSC_SIZE_SEND) { /* Case for frame size > 254 bytes */ |
| p_framebuff[2] = EXTENDED_FRAME_MARKER; |
| uint8_t mask = (iFrameData.sendDataLen) & EXTENDED_FRAME_MARKER; |
| p_framebuff[4] = mask; |
| mask = ((iFrameData.sendDataLen) >> 8) & EXTENDED_FRAME_MARKER; |
| p_framebuff[3] = mask; |
| /* store I frame */ |
| phNxpEse_memcpy(&(p_framebuff[5]), |
| iFrameData.p_data + iFrameData.dataOffset, |
| iFrameData.sendDataLen); |
| } else { /* Case for frame size < 254 bytes */ |
| /* store I frame length */ |
| p_framebuff[2] = iFrameData.sendDataLen; |
| frame_len = frame_len - 2; |
| /* store I frame */ |
| phNxpEse_memcpy(&(p_framebuff[3]), |
| iFrameData.p_data + iFrameData.dataOffset, |
| iFrameData.sendDataLen); |
| } |
| |
| p_framebuff[frame_len - 1] = |
| phNxpEseProto7816_ComputeLRC(p_framebuff, 0, (frame_len - 1)); |
| |
| status = phNxpEseProto7816_SendRawFrame(frame_len, p_framebuff); |
| |
| phNxpEse_free(p_framebuff); |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_SetNextIframeContxt |
| * |
| * Description This internal function is called to set the context for next |
| *I-frame. |
| * Not applicable for the first I-frame of the transceive |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_SetFirstIframeContxt(void) { |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.dataOffset = 0; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.seqNo = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.seqNo ^ 1; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_IFRAME; |
| if (phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.totalDataLen > |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo |
| .currentDataLenIFS) { |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.isChained = true; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.sendDataLen = |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo |
| .currentDataLenIFS; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.totalDataLen = |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.totalDataLen - |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo |
| .currentDataLenIFS; |
| } else { |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.sendDataLen = |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.totalDataLen; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.isChained = false; |
| } |
| ALOGD_IF(ese_debug_enabled, "I-Frame Data Len: %d Seq. no:%d", |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.sendDataLen, |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.seqNo); |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return ESESTATUS_SUCCESS; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_SetNextIframeContxt |
| * |
| * Description This internal function is called to set the context for next |
| *I-frame. |
| * Not applicable for the first I-frame of the transceive |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_SetNextIframeContxt(void) { |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| /* Expecting to reach here only after first of chained I-frame is sent and |
| * before the last chained is sent */ |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_IFRAME; |
| |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.seqNo = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.seqNo ^ 1; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.dataOffset = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.dataOffset + |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.currentDataLenIFS; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.p_data = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.p_data; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.currentDataLenIFS = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.currentDataLenIFS; |
| |
| // if chained |
| if (phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.totalDataLen > |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo |
| .currentDataLenIFS) { |
| ALOGD_IF(ese_debug_enabled, "Process Chained Frame"); |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.isChained = true; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.sendDataLen = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo |
| .currentDataLenIFS; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.totalDataLen = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.totalDataLen - |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo |
| .currentDataLenIFS; |
| } else { |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.isChained = false; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.sendDataLen = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.totalDataLen; |
| } |
| ALOGD_IF(ese_debug_enabled, "I-Frame Data Len: %d", |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.sendDataLen); |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return ESESTATUS_SUCCESS; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_ResetRecovery |
| * |
| * Description This internal function is called to do reset the recovery |
| *pareameters |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_SaveIframeData(uint8_t* p_data, |
| uint32_t data_len) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| ALOGD_IF(ese_debug_enabled, "Data[0]=0x%x len=%d Data[%d]=0x%x", p_data[0], |
| data_len, data_len - 1, p_data[data_len - 1]); |
| if (ESESTATUS_SUCCESS != phNxpEse_StoreDatainList(data_len, p_data)) { |
| ALOGE("%s - Error storing chained data in list", __FUNCTION__); |
| } else { |
| status = ESESTATUS_SUCCESS; |
| } |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_ResetRecovery |
| * |
| * Description This internal function is called to do reset the recovery |
| *pareameters |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_ResetRecovery(void) { |
| phNxpEseProto7816_3_Var.recoveryCounter = 0; |
| return ESESTATUS_SUCCESS; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_RecoverySteps |
| * |
| * Description This internal function is called when 7816-3 stack failed to |
| *recover |
| * after PH_PROTO_7816_FRAME_RETRY_COUNT, and the interface has |
| *to be |
| * recovered |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_RecoverySteps(void) { |
| if (phNxpEseProto7816_3_Var.recoveryCounter <= GET_FRAME_RETRY_COUNT()) { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| INTF_RESET_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.sFrameType = |
| INTF_RESET_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_S_INTF_RST; |
| } else { /* If recovery fails */ |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; |
| ALOGE("%s Recovery failed", __FUNCTION__); |
| } |
| return ESESTATUS_SUCCESS; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_DecodeSecureTimer |
| * |
| * Description This internal function is to decode the secure timer. |
| * value from the payload |
| * Returns void |
| * |
| ******************************************************************************/ |
| static void phNxpEseProto7816_DecodeSecureTimer(uint8_t* frameOffset, |
| unsigned int* secureTimer, |
| uint8_t* p_data) { |
| uint8_t byteCounter = 0; |
| uint8_t dataLength = p_data[++(*frameOffset)]; /* To get the L of TLV */ |
| if (dataLength > 0) { |
| /* V of TLV: Retrieve each byte(4 byte) and push it to get the secure timer |
| * value (unsigned long) */ |
| for (byteCounter = 1; byteCounter <= dataLength; byteCounter++) { |
| (*frameOffset)++; |
| *secureTimer = (*secureTimer) << 8; |
| *secureTimer |= p_data[(*frameOffset)]; |
| } |
| } else { |
| (*frameOffset)++; /* Goto the end of current marker if length is zero */ |
| } |
| return; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_DecodeSFrameIFSData |
| * |
| * Description This internal function is to decode S-frame payload. |
| * Returns void |
| * |
| ******************************************************************************/ |
| static void phNxpEseProto7816_DecodeSFrameIFSData(uint8_t* p_data) { |
| uint16_t ifsd_data = 0; |
| if (p_data[2] == 1) { |
| ifsd_data = p_data[3]; |
| } else if (p_data[2] == 2) { |
| ifsd_data = p_data[3]; |
| ifsd_data <<= 8; |
| ifsd_data |= p_data[4]; |
| } |
| if (ifsd_data == phNxpEseProto7816_3_Var.currentIFSDSize) { |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.currentDataLenIFS = |
| phNxpEseProto7816_3_Var.currentIFSDSize; |
| ALOGD_IF(ese_debug_enabled, "%s IFS adjustment: Max DataLen=%d \n", |
| __FUNCTION__, |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo |
| .currentDataLenIFS); |
| } else { |
| ALOGE("%s ERROR IFS adjustment: Max DataLen=%d \n", __FUNCTION__, |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo |
| .currentDataLenIFS); |
| } |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_DecodeSFrameATRData |
| * |
| * Description This internal function is to decode S-frame payload. |
| * Returns void |
| * |
| ******************************************************************************/ |
| static void phNxpEseProto7816_DecodeSFrameATRData(uint8_t* p_data) { |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.maxDataLenIFSC = 0; |
| /* Default IFSC size */ |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.defaultDataLenIFSC = |
| p_data[16]; |
| // phNxpEse_memcpy(phNxpEseProto7816_3_Var.pAtrData, &p_data[3], p_data[2]); |
| /* Max IFSC size */ |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.maxDataLenIFSC = |
| (p_data[18] << 8); |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.maxDataLenIFSC |= |
| (p_data[19]); |
| if (!p_data[2]) |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.maxDataLenIFSC = |
| IFSC_SIZE_SEND; |
| |
| phNxpEse_memcpy(&phNxpEseProto7816_3_Var.atrInfo.len, |
| &p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET], |
| sizeof(phNxpEseProto7816_ATR_Info_t)); |
| |
| ALOGD_IF( |
| ese_debug_enabled, |
| "%s Max DataLen=%d Current DataLen=%d Default DataLen=%d \n", |
| __FUNCTION__, |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.maxDataLenIFSC, |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.currentDataLenIFS, |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo |
| .defaultDataLenIFSC); |
| ALOGD_IF(ese_debug_enabled, "ATR Data Follows"); |
| ALOGD_IF(ese_debug_enabled, "======================"); |
| ALOGD_IF(ese_debug_enabled, "ATR Length = %d", |
| phNxpEseProto7816_3_Var.atrInfo.len); |
| ALOGD_IF(ese_debug_enabled, "Vendor ID = 0x%.2x%.2x%.2x%.2x%.2x", |
| phNxpEseProto7816_3_Var.atrInfo.vendorID[0], |
| phNxpEseProto7816_3_Var.atrInfo.vendorID[1], |
| phNxpEseProto7816_3_Var.atrInfo.vendorID[2], |
| phNxpEseProto7816_3_Var.atrInfo.vendorID[3], |
| phNxpEseProto7816_3_Var.atrInfo.vendorID[4]); |
| ALOGD_IF(ese_debug_enabled, "DLL-IC = supports T%d", |
| phNxpEseProto7816_3_Var.atrInfo.dll_IC); |
| ALOGD_IF(ese_debug_enabled, "BGT = %d ms", |
| (phNxpEseProto7816_3_Var.atrInfo.bgt[0] << 8) | |
| (phNxpEseProto7816_3_Var.atrInfo.bgt[1])); |
| ALOGD_IF(ese_debug_enabled, "BWT = %d ms", |
| phNxpEseProto7816_3_Var.atrInfo.bwt[0] << 8 | |
| phNxpEseProto7816_3_Var.atrInfo.bwt[1]); |
| ALOGD_IF(ese_debug_enabled, "Max supported frequency = %d Hz", |
| phNxpEseProto7816_3_Var.atrInfo.maxFreq[0] << 8 | |
| phNxpEseProto7816_3_Var.atrInfo.maxFreq[1]); |
| ALOGD_IF(ese_debug_enabled, "Checksum LRC(0)/CRC(1) supports = 0x%x", |
| phNxpEseProto7816_3_Var.atrInfo.checksum); |
| ALOGD_IF(ese_debug_enabled, "DefaultIFSC = %d bytes", |
| phNxpEseProto7816_3_Var.atrInfo.defaultIFSC); |
| ALOGD_IF(ese_debug_enabled, "Max IFSC = %d bytes", |
| phNxpEseProto7816_3_Var.atrInfo.maxIFSC[0] << 8 | |
| phNxpEseProto7816_3_Var.atrInfo.maxIFSC[1]); |
| ALOGD_IF(ese_debug_enabled, "Capabilities = 0x%x", |
| phNxpEseProto7816_3_Var.atrInfo.capabilities[0] << 8 | |
| phNxpEseProto7816_3_Var.atrInfo.capabilities[1]); |
| |
| if (phNxpEseProto7816_3_Var.atrInfo.vendorID[4] >= PH_SE_OS_VERSION_11) { |
| phNxpEse_memcpy(&phNxpEseProto7816_3_Var.extndAtrInfo.channelNo, |
| &p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] + |
| sizeof(phNxpEseProto7816_ATR_Info_t), |
| sizeof(phNxpEseProto7816_ATR_Info2_t)); |
| ALOGD_IF(ese_debug_enabled, "Channel Number = 0x%x", |
| phNxpEseProto7816_3_Var.extndAtrInfo.channelNo); |
| ALOGD_IF( |
| ese_debug_enabled, "OS Type = %s", |
| (phNxpEseProto7816_3_Var.extndAtrInfo.osType == 0x01 ? "JCOP Mode" |
| : "OSU Mode")); |
| } |
| if (phNxpEseProto7816_3_Var.atrInfo.vendorID[PH_PROTO_ATR_RSP_VENDOR_ID_LEN - |
| 1] >= PH_SE_OS_VERSION_20) { |
| phNxpEse_setOsVersion(OS_VERSION_6_2); |
| } else if (phNxpEseProto7816_3_Var.atrInfo |
| .vendorID[PH_PROTO_ATR_RSP_VENDOR_ID_LEN - 1] >= |
| PH_SE_OS_VERSION_11) { |
| phNxpEse_setOsVersion(OS_VERSION_5_2_2); |
| } else if (phNxpEseProto7816_3_Var.atrInfo |
| .vendorID[PH_PROTO_ATR_RSP_VENDOR_ID_LEN - 1] == |
| PH_SE_OS_VERSION_10) { |
| phNxpEse_setOsVersion(OS_VERSION_5_2); |
| } else if (phNxpEseProto7816_3_Var.atrInfo |
| .vendorID[PH_PROTO_ATR_RSP_VENDOR_ID_LEN - 1] == |
| PH_PROTO_7816_VALUE_ZERO) { |
| phNxpEse_setOsVersion(OS_VERSION_5_1); |
| } |
| |
| ALOGD_IF(ese_debug_enabled, "======================"); |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_DecodeSFrameData |
| * |
| * Description This internal function is to decode S-frame payload. |
| * Returns void |
| * |
| ******************************************************************************/ |
| static void phNxpEseProto7816_DecodeSFrameSecureTimerData(uint8_t* p_data) { |
| uint8_t maxSframeLen = 0, dataType = 0, frameOffset = 0; |
| frameOffset = PH_PROPTO_7816_FRAME_LENGTH_OFFSET; |
| maxSframeLen = |
| p_data[frameOffset] + |
| frameOffset; /* to be in sync with offset which starts from index 0 */ |
| |
| /* Secure Timer specific parser */ |
| while (maxSframeLen > frameOffset) { |
| frameOffset += 1; /* To get the Type (TLV) */ |
| dataType = p_data[frameOffset]; |
| ALOGD_IF(ese_debug_enabled, "%s frameoffset=%d value=0x%x\n", __FUNCTION__, |
| frameOffset, p_data[frameOffset]); |
| switch (dataType) /* Type (TLV) */ |
| { |
| case PH_PROPTO_7816_SFRAME_TIMER1: |
| phNxpEseProto7816_DecodeSecureTimer( |
| &frameOffset, |
| &phNxpEseProto7816_3_Var.secureTimerParams.secureTimer1, p_data); |
| break; |
| case PH_PROPTO_7816_SFRAME_TIMER2: |
| phNxpEseProto7816_DecodeSecureTimer( |
| &frameOffset, |
| &phNxpEseProto7816_3_Var.secureTimerParams.secureTimer2, p_data); |
| break; |
| case PH_PROPTO_7816_SFRAME_TIMER3: |
| phNxpEseProto7816_DecodeSecureTimer( |
| &frameOffset, |
| &phNxpEseProto7816_3_Var.secureTimerParams.secureTimer3, p_data); |
| break; |
| default: |
| frameOffset += |
| p_data[frameOffset + 1]; /* Goto the end of current marker */ |
| break; |
| } |
| } |
| ALOGD_IF(ese_debug_enabled, "secure timer t1 = 0x%x t2 = 0x%x t3 = 0x%x", |
| phNxpEseProto7816_3_Var.secureTimerParams.secureTimer1, |
| phNxpEseProto7816_3_Var.secureTimerParams.secureTimer2, |
| phNxpEseProto7816_3_Var.secureTimerParams.secureTimer3); |
| return; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_DecodeFrame |
| * |
| * Description This internal function is used to |
| * 1. Identify the received frame |
| * 2. If the received frame is I-frame with expected sequence |
| number, store it or else send R-NACK |
| 3. If the received frame is R-frame, |
| 3.1 R-ACK with expected seq. number: Send the next |
| chained I-frame |
| 3.2 R-ACK with different sequence number: Sebd the R-Nack |
| 3.3 R-NACK: Re-send the last frame |
| 4. If the received frame is S-frame, send back the correct |
| S-frame response. |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_DecodeFrame(uint8_t* p_data, |
| uint32_t data_len) { |
| ESESTATUS status = ESESTATUS_SUCCESS; |
| uint8_t pcb; |
| phNxpEseProto7816_PCB_bits_t pcb_bits; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| ALOGD_IF(ese_debug_enabled, "Retry Counter = %d\n", |
| phNxpEseProto7816_3_Var.recoveryCounter); |
| pcb = p_data[PH_PROPTO_7816_PCB_OFFSET]; |
| // memset(&phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.rcvPcbBits, 0x00, |
| // sizeof(struct PCB_BITS)); |
| phNxpEse_memset(&pcb_bits, 0x00, sizeof(phNxpEseProto7816_PCB_bits_t)); |
| phNxpEse_memcpy(&pcb_bits, &pcb, sizeof(uint8_t)); |
| |
| if (0x00 == pcb_bits.msb) /* I-FRAME decoded should come here */ |
| { |
| if (!phNxpEseProto7816_ResendLastSFrameReq()) { |
| ALOGD_IF(ese_debug_enabled, "%s I-Frame Received", __FUNCTION__); |
| phNxpEseProto7816_CheckAndNotifyWtx(WTX_END); |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = IFRAME; |
| if (phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo.seqNo != |
| pcb_bits.bit7) // != pcb_bits->bit7) |
| { |
| ALOGD_IF(ese_debug_enabled, "%s I-Frame lastRcvdIframeInfo.seqNo:0x%x", |
| __FUNCTION__, pcb_bits.bit7); |
| phNxpEseProto7816_ResetRecovery(); |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo.seqNo = 0x00; |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo.seqNo |= |
| pcb_bits.bit7; |
| |
| if (pcb_bits.bit6) { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo.isChained = |
| true; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo.errCode = |
| NO_ERROR; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_R_ACK; |
| if (EXTENDED_FRAME_MARKER == p_data[2] && |
| (data_len > 6)) /* Checking for extended frame prologue */ |
| { |
| status = phNxpEseProto7816_SaveIframeData(&p_data[5], data_len - 6); |
| } else if (data_len > 4) { |
| status = phNxpEseProto7816_SaveIframeData(&p_data[3], data_len - 4); |
| } else { |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_R_NACK; |
| ALOGD_IF(ese_debug_enabled, "%s Invalid IframeData", __FUNCTION__); |
| } |
| } else { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo.isChained = |
| false; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| if (EXTENDED_FRAME_MARKER == p_data[2] && |
| (data_len > 6)) /* Checking for extended frame prologue */ |
| { |
| status = phNxpEseProto7816_SaveIframeData(&p_data[5], data_len - 6); |
| } else if (data_len > 4) { |
| status = phNxpEseProto7816_SaveIframeData(&p_data[3], data_len - 4); |
| } else { |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_R_NACK; |
| ALOGD_IF(ese_debug_enabled, "%s Invalid IframeData", __FUNCTION__); |
| } |
| } |
| } else { |
| phNxpEse_Sleep(GET_DELAY_ERROR_RECOVERY()); |
| if (phNxpEseProto7816_3_Var.recoveryCounter < GET_FRAME_RETRY_COUNT()) { |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo.errCode = |
| OTHER_ERROR; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_R_NACK; |
| phNxpEseProto7816_3_Var.recoveryCounter++; |
| } else { |
| phNxpEseProto7816_RecoverySteps(); |
| phNxpEseProto7816_3_Var.recoveryCounter++; |
| } |
| } |
| } |
| } else if ((0x01 == pcb_bits.msb) && |
| (0x00 == pcb_bits.bit7)) /* R-FRAME decoded should come here */ |
| { |
| ALOGD_IF(ese_debug_enabled, "%s R-Frame Received", __FUNCTION__); |
| phNxpEseProto7816_CheckAndNotifyWtx(WTX_END); |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = RFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo.seqNo = |
| 0; // = 0; |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo.seqNo |= |
| pcb_bits.bit5; |
| |
| if ((pcb_bits.lsb == 0x00) && (pcb_bits.bit2 == 0x00)) { |
| if (!phNxpEseProto7816_ResendLastSFrameReq()) { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo.errCode = |
| NO_ERROR; |
| phNxpEseProto7816_ResetRecovery(); |
| if (phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo.seqNo != |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.seqNo) { |
| status = phNxpEseProto7816_SetNextIframeContxt(); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_IFRAME; |
| } else { |
| // error handling. |
| } |
| } |
| } /* Error handling 1 : Parity error */ |
| else if (((pcb_bits.lsb == 0x01) && (pcb_bits.bit2 == 0x00)) || |
| /* Error handling 2: Other indicated error */ |
| ((pcb_bits.lsb == 0x00) && (pcb_bits.bit2 == 0x01)) || |
| /* Error handling 3 : Frame Missing error */ |
| ((pcb_bits.lsb == 0x01) && (pcb_bits.bit2 == 0x01))) { |
| phNxpEse_Sleep(GET_DELAY_ERROR_RECOVERY()); |
| if ((pcb_bits.lsb == 0x00) && (pcb_bits.bit2 == 0x01)) { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo.errCode = |
| OTHER_ERROR; |
| } else if ((pcb_bits.lsb == 0x01) && (pcb_bits.bit2 == 0x00)) { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo.errCode = |
| PARITY_ERROR; |
| } else { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo.errCode = |
| SOF_MISSED_ERROR; |
| } |
| if (phNxpEseProto7816_3_Var.recoveryCounter < GET_FRAME_RETRY_COUNT()) { |
| if (phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType == IFRAME) { |
| /*Only for R-NACK other issue re sync*/ |
| if ((pcb_bits.lsb == 0x00) && (pcb_bits.bit2 == 0x01)) { |
| if (phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo |
| .seqNo != phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx |
| .IframeInfo.seqNo && |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo |
| .isChained == false) { |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_S_RSYNC; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo |
| .sFrameType = RESYNCH_REQ; |
| } else { |
| /*If R-NACK with sequence no matching then also reissue frame*/ |
| phNxpEse_memcpy(&phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx, |
| &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx, |
| sizeof(phNxpEseProto7816_NextTx_Info_t)); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_IFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; |
| } |
| } else { |
| phNxpEse_memcpy(&phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx, |
| &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx, |
| sizeof(phNxpEseProto7816_NextTx_Info_t)); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_IFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; |
| } |
| } else if (phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType == |
| RFRAME) { |
| /* Usecase to reach the below case: |
| I-frame sent first, followed by R-NACK and we receive a R-NACK with |
| last sent I-frame sequence number*/ |
| if ((phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo |
| .seqNo == |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.seqNo) && |
| (phNxpEseProto7816_3_Var.lastSentNonErrorframeType == IFRAME)) { |
| phNxpEse_memcpy(&phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx, |
| &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx, |
| sizeof(phNxpEseProto7816_NextTx_Info_t)); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_IFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; |
| } |
| /* Usecase to reach the below case: |
| R-frame sent first, followed by R-NACK and we receive a R-NACK with |
| next expected I-frame sequence number*/ |
| else if ((phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo |
| .seqNo != phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx |
| .IframeInfo.seqNo) && |
| (phNxpEseProto7816_3_Var.lastSentNonErrorframeType == |
| RFRAME)) { |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo.errCode = |
| NO_ERROR; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_R_ACK; |
| } |
| /* Usecase to reach the below case: |
| I-frame sent first, followed by R-NACK and we receive a R-NACK with |
| next expected I-frame sequence number + all the other unexpected |
| scenarios */ |
| else { |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo.errCode = |
| OTHER_ERROR; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_R_NACK; |
| } |
| } else if (phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType == |
| SFRAME) { |
| /* Copy the last S frame sent */ |
| phNxpEse_memcpy(&phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx, |
| &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx, |
| sizeof(phNxpEseProto7816_NextTx_Info_t)); |
| } |
| phNxpEseProto7816_3_Var.recoveryCounter++; |
| } else { |
| phNxpEseProto7816_RecoverySteps(); |
| phNxpEseProto7816_3_Var.recoveryCounter++; |
| } |
| // resend previously send I frame |
| } else /* Error handling 4 */ |
| { |
| phNxpEse_Sleep(GET_DELAY_ERROR_RECOVERY()); |
| if (phNxpEseProto7816_3_Var.recoveryCounter < GET_FRAME_RETRY_COUNT()) { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo.errCode = |
| UNDEFINED_ERROR; |
| phNxpEseProto7816_3_Var.recoveryCounter++; |
| } else { |
| phNxpEseProto7816_RecoverySteps(); |
| phNxpEseProto7816_3_Var.recoveryCounter++; |
| } |
| } |
| } else if ((0x01 == pcb_bits.msb) && |
| (0x01 == pcb_bits.bit7)) /* S-FRAME decoded should come here */ |
| { |
| ALOGD_IF(ese_debug_enabled, "%s S-Frame Received", __FUNCTION__); |
| int32_t frameType = (int32_t)(pcb & 0x3F); /*discard upper 2 bits */ |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = SFRAME; |
| if (frameType != WTX_REQ) { |
| phNxpEseProto7816_CheckAndNotifyWtx(WTX_END); |
| } |
| phNxpEseProto7816_ResetRecovery(); |
| switch (frameType) { |
| case RESYNCH_REQ: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| RESYNCH_REQ; |
| break; |
| case RESYNCH_RSP: |
| if (phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo |
| .errCode == OTHER_ERROR) { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo |
| .sFrameType = RESYNCH_RSP; |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdRframeInfo.errCode = |
| NO_ERROR; |
| phNxpEse_memcpy(&phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx, |
| &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx, |
| sizeof(phNxpEseProto7816_NextTx_Info_t)); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_IFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = IFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.seqNo = |
| PH_PROTO_7816_VALUE_ZERO; |
| /* Initialized the I-Frame sequence number as boot time, |
| as R-SYNCH has reset the Jcop seq number */ |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo.seqNo = |
| PH_PROTO_7816_VALUE_ONE; |
| } else { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo |
| .sFrameType = RESYNCH_RSP; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = UNKNOWN; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| } |
| break; |
| case IFS_REQ: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| IFS_REQ; |
| break; |
| case IFS_RES: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| IFS_RES; |
| if (p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) |
| phNxpEseProto7816_DecodeSFrameIFSData(p_data); |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = UNKNOWN; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| break; |
| case ABORT_REQ: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| ABORT_REQ; |
| break; |
| case ABORT_RES: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| ABORT_RES; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = UNKNOWN; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| break; |
| case WTX_REQ: |
| phNxpEseProto7816_3_Var.wtx_counter++; |
| ALOGD_IF(ese_debug_enabled, "%s Wtx_counter value - %lu", __FUNCTION__, |
| phNxpEseProto7816_3_Var.wtx_counter); |
| ALOGD_IF(ese_debug_enabled, "%s Wtx_counter wtx_counter_limit - %lu", |
| __FUNCTION__, phNxpEseProto7816_3_Var.wtx_counter_limit); |
| /* Previous sent frame is some S-frame but not WTX response S-frame */ |
| if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0 && |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.SframeInfo.sFrameType != |
| WTX_RSP && |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType == SFRAME) { |
| /* Goto recovery if it |
| keep coming here for more than recovery counter max. value */ |
| if (phNxpEseProto7816_3_Var.recoveryCounter < |
| GET_FRAME_RETRY_COUNT()) { /* Re-transmitting the previous |
| sent S-frame */ |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx; |
| phNxpEseProto7816_3_Var.recoveryCounter++; |
| } else { |
| phNxpEseProto7816_RecoverySteps(); |
| phNxpEseProto7816_3_Var.recoveryCounter++; |
| } |
| } else { |
| /* Checking for WTX counter with max. allowed WTX count */ |
| if (phNxpEseProto7816_3_Var.wtx_counter == |
| phNxpEseProto7816_3_Var.wtx_counter_limit) { |
| phNxpEseProto7816_CheckAndNotifyWtx(WTX_END); |
| if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) { |
| ALOGD_IF(ese_debug_enabled, |
| "%s Power cycle to eSE max " |
| "WTX received", |
| __FUNCTION__); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| status = ESESTATUS_TRANSCEIVE_FAILED; |
| } else { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo |
| .sFrameType = INTF_RESET_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo |
| .sFrameType = INTF_RESET_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_S_INTF_RST; |
| ALOGD_IF(ese_debug_enabled, |
| "%s Interface Reset to eSE wtx" |
| " count reached!!!", |
| __FUNCTION__); |
| } |
| } else { |
| phNxpEse_Sleep(GET_DELAY_ERROR_RECOVERY()); |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo |
| .sFrameType = WTX_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.sFrameType = |
| WTX_RSP; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_S_WTX_RSP; |
| } |
| } |
| break; |
| case WTX_RSP: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| WTX_RSP; |
| break; |
| case INTF_RESET_REQ: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| INTF_RESET_REQ; |
| break; |
| case INTF_RESET_RSP: |
| phNxpEseProto7816_ResetProtoParams(); |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| INTF_RESET_RSP; |
| if (p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) { |
| phNxpEseProto7816_DecodeSFrameATRData(p_data); |
| } else { |
| phNxpEse_setOsVersion(OS_VERSION_4_0); |
| } |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = UNKNOWN; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| break; |
| case PROP_END_APDU_REQ: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| PROP_END_APDU_REQ; |
| break; |
| case PROP_END_APDU_RSP: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| PROP_END_APDU_RSP; |
| if (p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) |
| phNxpEseProto7816_DecodeSFrameSecureTimerData(p_data); |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = UNKNOWN; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| break; |
| case HARD_RESET_REQ: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| HARD_RESET_REQ; |
| break; |
| case HARD_RESET_RSP: |
| // This is 4ms delay and delay of 1ms in also there in line 1401 before |
| // next Tx |
| phNxpEse_Sleep(HARD_RESET_RES_DELAY); |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| HARD_RESET_RSP; |
| if (p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) { |
| /*Response status either success/fail*/ |
| if (!p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET + 1]) |
| status = ESESTATUS_FAILED; |
| else |
| status = ESESTATUS_SUCCESS; |
| } |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = UNKNOWN; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| break; |
| case ATR_RSP: |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdSframeInfo.sFrameType = |
| ATR_RSP; |
| if (p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET] > 0) { |
| phNxpEseProto7816_DecodeSFrameATRData(p_data); |
| phNxpEse_StoreDatainList( |
| p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET], |
| &p_data[PH_PROPTO_7816_FRAME_LENGTH_OFFSET + 1]); |
| } else { |
| phNxpEse_setOsVersion(OS_VERSION_4_0); |
| } |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = UNKNOWN; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| break; |
| default: |
| ALOGE("%s Wrong S-Frame Received", __FUNCTION__); |
| break; |
| } |
| /*After S-Frame Rx 1 msec delay before next Tx*/ |
| if ((GET_CHIP_OS_VERSION() != OS_VERSION_4_0) && |
| (frameType != PROP_END_APDU_RSP)) { |
| phNxpEse_Sleep(1000); |
| } |
| } else { |
| ALOGD_IF(ese_debug_enabled, "%s Wrong-Frame Received", __FUNCTION__); |
| } |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_ProcessResponse |
| * |
| * Description This internal function is used to |
| * 1. Check the LRC |
| * 2. Initiate decoding of received frame of data. |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_ProcessResponse(void) { |
| uint32_t data_len = 0; |
| uint8_t* p_data = NULL; |
| ESESTATUS status = ESESTATUS_FAILED; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| status = phNxpEseProto7816_GetRawFrame(&data_len, &p_data); |
| ALOGD_IF(ese_debug_enabled, "%s p_data ----> %p len ----> 0x%x", __FUNCTION__, |
| p_data, data_len); |
| if (ESESTATUS_SUCCESS == status) { |
| /* Resetting the timeout counter */ |
| phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; |
| /* LRC check followed */ |
| status = phNxpEseProto7816_CheckLRC(data_len, p_data); |
| if (status == ESESTATUS_SUCCESS) { |
| /* Resetting the RNACK retry counter */ |
| phNxpEseProto7816_3_Var.rnack_retry_counter = PH_PROTO_7816_VALUE_ZERO; |
| status = phNxpEseProto7816_DecodeFrame(p_data, data_len); |
| } else { |
| ALOGE("%s LRC Check failed", __FUNCTION__); |
| if (phNxpEseProto7816_3_Var.rnack_retry_counter < |
| phNxpEseProto7816_3_Var.rnack_retry_limit) { |
| /*If Last sent Non-error frame is S-Frame*/ |
| if (!phNxpEseProto7816_ResendLastSFrameReq()) { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = INVALID; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo.errCode = |
| PARITY_ERROR; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo.seqNo = |
| (!phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo |
| .seqNo) |
| << 4; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_R_NACK; |
| if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) { |
| phNxpEse_Sleep(GET_DELAY_ERROR_RECOVERY()); |
| } |
| } |
| phNxpEseProto7816_3_Var.rnack_retry_counter++; |
| } else { |
| phNxpEseProto7816_3_Var.rnack_retry_counter = PH_PROTO_7816_VALUE_ZERO; |
| /* Re-transmission failed completely, Going to exit */ |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; |
| } |
| } |
| } else { |
| ALOGD_IF(ese_debug_enabled, "%s phNxpEseProto7816_GetRawFrame failed", |
| __FUNCTION__); |
| if ((SFRAME == phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType) && |
| ((WTX_RSP == |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.SframeInfo.sFrameType) || |
| (RESYNCH_RSP == |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.SframeInfo.sFrameType))) { |
| if (phNxpEseProto7816_3_Var.rnack_retry_counter < |
| phNxpEseProto7816_3_Var.rnack_retry_limit) { |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = INVALID; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = RFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo.errCode = |
| OTHER_ERROR; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.RframeInfo.seqNo = |
| (!phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo.seqNo) |
| << 4; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_R_NACK; |
| phNxpEseProto7816_3_Var.rnack_retry_counter++; |
| } else { |
| phNxpEseProto7816_3_Var.rnack_retry_counter = PH_PROTO_7816_VALUE_ZERO; |
| /* Re-transmission failed completely, Going to exit */ |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; |
| } |
| } else { |
| phNxpEse_Sleep(GET_DELAY_ERROR_RECOVERY()); |
| /* re transmit the frame */ |
| if (phNxpEseProto7816_3_Var.timeoutCounter < |
| PH_PROTO_7816_TIMEOUT_RETRY_COUNT) { |
| phNxpEseProto7816_3_Var.timeoutCounter++; |
| ALOGD_IF(ese_debug_enabled, "%s re-transmitting the previous frame", |
| __FUNCTION__); |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx = |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx; |
| } else { |
| /* Re-transmission failed completely, Going to exit */ |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) { |
| status = ESESTATUS_FAILED; |
| } |
| phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; |
| ALOGD_IF(ese_debug_enabled, "%s calling phNxpEse_StoreDatainList", |
| __FUNCTION__); |
| phNxpEse_StoreDatainList(data_len, p_data); |
| } |
| } |
| } |
| ALOGD_IF(ese_debug_enabled, "Exit %s Status 0x%x", __FUNCTION__, status); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function TransceiveProcess |
| * |
| * Description This internal function is used to |
| * 1. Send the raw data received from application after |
| *computing LRC |
| * 2. Receive the response data from ESE, decode, process |
| *and |
| * store the data. |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS TransceiveProcess(void) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| sFrameInfo_t sFrameInfo; |
| memset(&sFrameInfo, 0, sizeof(sFrameInfo_t)); |
| |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| while (phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState != |
| IDLE_STATE) { |
| ALOGD_IF(ese_debug_enabled, "%s nextTransceiveState %x", __FUNCTION__, |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState); |
| switch (phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState) { |
| case SEND_IFRAME: |
| status = phNxpEseProto7816_SendIframe( |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo); |
| break; |
| case SEND_R_ACK: |
| status = phNxpEseProto7816_sendRframe(RACK); |
| break; |
| case SEND_R_NACK: |
| status = phNxpEseProto7816_sendRframe(RNACK); |
| if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) { |
| phNxpEse_Sleep(GET_DELAY_ERROR_RECOVERY()); |
| } |
| break; |
| case SEND_S_RSYNC: |
| sFrameInfo.sFrameType = RESYNCH_REQ; |
| status = phNxpEseProto7816_SendSFrame(sFrameInfo); |
| break; |
| case SEND_S_INTF_RST: |
| sFrameInfo.sFrameType = INTF_RESET_REQ; |
| status = phNxpEseProto7816_SendSFrame(sFrameInfo); |
| break; |
| case SEND_S_IFS_ADJ: |
| sFrameInfo.sFrameType = IFS_REQ; |
| status = phNxpEseProto7816_SendSFrame(sFrameInfo); |
| break; |
| case SEND_S_EOS: |
| sFrameInfo.sFrameType = PROP_END_APDU_REQ; |
| sFrameInfo.len = |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.len; |
| sFrameInfo.p_data = |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.p_data; |
| status = phNxpEseProto7816_SendSFrame(sFrameInfo); |
| break; |
| case SEND_S_WTX_RSP: |
| sFrameInfo.sFrameType = WTX_RSP; |
| status = phNxpEseProto7816_SendSFrame(sFrameInfo); |
| phNxpEseProto7816_CheckAndNotifyWtx(WTX_ONGOING); |
| break; |
| case SEND_S_HRD_RST: |
| sFrameInfo.sFrameType = HARD_RESET_REQ; |
| status = phNxpEseProto7816_SendSFrame(sFrameInfo); |
| break; |
| case SEND_S_ATR_REQ: |
| sFrameInfo.sFrameType = ATR_REQ; |
| status = phNxpEseProto7816_SendSFrame(sFrameInfo); |
| break; |
| default: |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| break; |
| } |
| if (ESESTATUS_SUCCESS == status) { |
| phNxpEse_memcpy(&phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx, |
| &phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx, |
| sizeof(phNxpEseProto7816_NextTx_Info_t)); |
| status = phNxpEseProto7816_ProcessResponse(); |
| } else { |
| ALOGE("%s Transceive send failed, going to recovery!", __FUNCTION__); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| IDLE_STATE; |
| } |
| }; |
| /*Timeout condition when previously WTX_ONGOING is notified |
| *WTX_END shall be notified from here */ |
| phNxpEseProto7816_CheckAndNotifyWtx(WTX_END); |
| ALOGD_IF(ese_debug_enabled, "Exit %s Status 0x%x", __FUNCTION__, status); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_CheckAndNotifyWtx |
| * |
| * Description This function is used to |
| * 1. Check any WTX received previously |
| *computing LRC |
| * 2. Check WTX_counter limit is reached wtx_ntf limit |
| *and |
| * 3. Notify if wtx counter is greater than wtx_ntf |
| * |
| * Returns None. |
| * |
| ******************************************************************************/ |
| static void phNxpEseProto7816_CheckAndNotifyWtx(phNxpEse_wtxState state) { |
| if (phNxpEseProto7816_3_Var.wtx_counter) { |
| if (state == WTX_END) { |
| if (phNxpEseProto7816_3_Var.wtx_counter >= |
| phNxpEseProto7816_3_Var.wtx_ntf_limit) { |
| phNxpEse_NotifySEWtxRequest(WTX_END); |
| } |
| phNxpEseProto7816_3_Var.wtx_counter = 0; |
| } else if (state == WTX_ONGOING) { |
| if (phNxpEseProto7816_3_Var.wtx_counter == |
| phNxpEseProto7816_3_Var.wtx_ntf_limit) { |
| phNxpEse_NotifySEWtxRequest(WTX_ONGOING); |
| } |
| } |
| } |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_Transceive |
| * |
| * Description This function is used to |
| * 1. Send the raw data received from application after |
| *computing LRC |
| * 2. Receive the response data from ESE, decode, process |
| *and |
| * store the data. |
| * 3. Get the final complete data and sent back to application |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_Transceive(phNxpEse_data* pCmd, |
| phNxpEse_data* pRsp) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| ESESTATUS wStatus = ESESTATUS_FAILED; |
| phNxpEse_data pRes; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| if ((NULL == pCmd) || (NULL == pRsp) || |
| (phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState != |
| PH_NXP_ESE_PROTO_7816_IDLE)) |
| return status; |
| phNxpEse_memset(&pRes, 0x00, sizeof(phNxpEse_data)); |
| /* Updating the transceive information to the protocol stack */ |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_TRANSCEIVE; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.p_data = pCmd->p_data; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.totalDataLen = |
| pCmd->len; |
| ALOGD_IF(ese_debug_enabled, "Transceive data ptr 0x%p len:%d", pCmd->p_data, |
| pCmd->len); |
| status = phNxpEseProto7816_SetFirstIframeContxt(); |
| status = TransceiveProcess(); |
| if (ESESTATUS_FAILED == status || ESESTATUS_TRANSCEIVE_FAILED == status) { |
| /* ESE hard reset to be done */ |
| ALOGE("Transceive failed, hard reset to proceed"); |
| wStatus = phNxpEse_GetData(&pRes.len, &pRes.p_data); |
| if (ESESTATUS_SUCCESS == wStatus) { |
| ALOGD_IF(ese_debug_enabled, |
| "%s Data successfully received at 7816, packaging to " |
| "send upper layers: DataLen = %d", |
| __FUNCTION__, pRes.len); |
| } |
| } else { |
| // fetch the data info and report to upper layer. |
| wStatus = phNxpEse_GetData(&pRes.len, &pRes.p_data); |
| if (ESESTATUS_SUCCESS == wStatus) { |
| ALOGD_IF(ese_debug_enabled, |
| "%s Data successfully received at 7816, packaging to " |
| "send upper layers: DataLen = %d", |
| __FUNCTION__, pRes.len); |
| } else |
| status = ESESTATUS_FAILED; |
| } |
| |
| /* Copy the data to be read by the upper layer via transceive api */ |
| pRsp->len = pRes.len; |
| pRsp->p_data = pRes.p_data; |
| |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_IDLE; |
| phNxpEseProto7816_3_Var.reset_type = RESET_TYPE_NONE; |
| ALOGD_IF(ese_debug_enabled, "Exit %s Status 0x%x", __FUNCTION__, status); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_RSync |
| * |
| * Description This function is used to send the RSync command |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_RSync(void) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_TRANSCEIVE; |
| /* send the end of session s-frame */ |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.sFrameType = |
| RESYNCH_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_RSYNC; |
| status = TransceiveProcess(); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_IDLE; |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_HardReset |
| * |
| * Description This function is used to send the spi hard reset command |
| * |
| * Returns On success return TRUE or else FALSE. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_HardReset(void) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_TRANSCEIVE; |
| /* send the hard reset s-frame command*/ |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.sFrameType = |
| HARD_RESET_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_S_HRD_RST; |
| status = TransceiveProcess(); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_IDLE; |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_ResetProtoParams |
| * |
| * Description This function is used to reset the 7816 protocol stack |
| *instance |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| static ESESTATUS phNxpEseProto7816_ResetProtoParams(void) { |
| unsigned long int tmpWTXCountlimit = PH_PROTO_7816_VALUE_ZERO; |
| unsigned long int tmpRNACKCountlimit = PH_PROTO_7816_VALUE_ZERO; |
| unsigned long int tmpWtxNtfCountlimit = PH_PROTO_7816_VALUE_ZERO; |
| tmpWTXCountlimit = phNxpEseProto7816_3_Var.wtx_counter_limit; |
| tmpRNACKCountlimit = phNxpEseProto7816_3_Var.rnack_retry_limit; |
| tmpWtxNtfCountlimit = phNxpEseProto7816_3_Var.wtx_ntf_limit; |
| phNxpEse_memset(&phNxpEseProto7816_3_Var, PH_PROTO_7816_VALUE_ZERO, |
| sizeof(phNxpEseProto7816_t)); |
| phNxpEseProto7816_3_Var.wtx_counter_limit = tmpWTXCountlimit; |
| phNxpEseProto7816_3_Var.rnack_retry_limit = tmpRNACKCountlimit; |
| phNxpEseProto7816_3_Var.wtx_ntf_limit = tmpWtxNtfCountlimit; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_IDLE; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = IDLE_STATE; |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdFrameType = INVALID; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = INVALID; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.maxDataLenIFSC = |
| IFSC_SIZE_SEND; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.defaultDataLenIFSC = |
| IFSC_SIZE_SEND; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.currentDataLenIFS = |
| IFSC_SIZE_SEND; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.p_data = NULL; |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.FrameType = INVALID; |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.maxDataLenIFSC = |
| IFSC_SIZE_SEND; |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.defaultDataLenIFSC = |
| IFSC_SIZE_SEND; |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.currentDataLenIFS = |
| IFSC_SIZE_SEND; |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.p_data = NULL; |
| /* Initialized with sequence number of the last I-frame sent */ |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.seqNo = |
| PH_PROTO_7816_VALUE_ONE; |
| /* Initialized with sequence number of the last I-frame received */ |
| phNxpEseProto7816_3_Var.phNxpEseRx_Cntx.lastRcvdIframeInfo.seqNo = |
| PH_PROTO_7816_VALUE_ONE; |
| /* Initialized with sequence number of the last I-frame received */ |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.IframeInfo.seqNo = |
| PH_PROTO_7816_VALUE_ONE; |
| phNxpEseProto7816_3_Var.recoveryCounter = PH_PROTO_7816_VALUE_ZERO; |
| phNxpEseProto7816_3_Var.timeoutCounter = PH_PROTO_7816_VALUE_ZERO; |
| phNxpEseProto7816_3_Var.wtx_counter = PH_PROTO_7816_VALUE_ZERO; |
| /* This update is helpful in-case a R-NACK is transmitted from the MW */ |
| phNxpEseProto7816_3_Var.lastSentNonErrorframeType = UNKNOWN; |
| phNxpEseProto7816_3_Var.rnack_retry_counter = PH_PROTO_7816_VALUE_ZERO; |
| return ESESTATUS_SUCCESS; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_Reset |
| * |
| * Description This function is used to reset the 7816 protocol stack |
| *instance |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_Reset(void) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| /* Resetting host protocol instance */ |
| phNxpEseProto7816_ResetProtoParams(); |
| if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) { |
| status = phNxpEseProto7816_HardReset(); |
| if (status == ESESTATUS_SUCCESS) { |
| /* Updating the ATR information(IFS,..) to 7816 stack */ |
| phNxpEse_data atrRsp; |
| phNxpEseProto7816_getAtr(&atrRsp); |
| phNxpEse_free(atrRsp.p_data); |
| } |
| } else { |
| /* Resynchronising ESE protocol instance */ |
| status = phNxpEseProto7816_RSync(); |
| } |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_Open |
| * |
| * Description This function is used to open the 7816 protocol stack |
| *instance |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_Open(phNxpEseProto7816InitParam_t initParam) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| status = phNxpEseProto7816_ResetProtoParams(); |
| ALOGD_IF(ese_debug_enabled, "%s: First open completed, Congratulations", |
| __FUNCTION__); |
| /* Update WTX max. limit */ |
| phNxpEseProto7816_3_Var.wtx_counter_limit = initParam.wtx_counter_limit; |
| phNxpEseProto7816_3_Var.rnack_retry_limit = initParam.rnack_retry_limit; |
| phNxpEseProto7816_3_Var.wtx_ntf_limit = initParam.wtx_ntf_limit; |
| if (initParam.interfaceReset) /* Do interface reset */ |
| { |
| status = phNxpEseProto7816_IntfReset(initParam.pSecureTimerParams); |
| if (ESESTATUS_SUCCESS == status) { |
| phNxpEse_memcpy(initParam.pSecureTimerParams, |
| &phNxpEseProto7816_3_Var.secureTimerParams, |
| sizeof(phNxpEseProto7816SecureTimer_t)); |
| } |
| } else /* Initialisation condition to achieve usecases like JCOP download */ |
| { |
| if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) { |
| status = phNxpEseProto7816_HardReset(); |
| /* Updating the ATR information (Eg: IFS,..) to 7816 stack */ |
| if (status == ESESTATUS_SUCCESS) { |
| phNxpEse_data atrRsp; |
| phNxpEseProto7816_getAtr(&atrRsp); |
| phNxpEse_free(atrRsp.p_data); |
| } |
| } else { |
| status = phNxpEseProto7816_RSync(); |
| } |
| } |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_Close |
| * |
| * Description This function is used to close the 7816 protocol stack |
| *instance |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_Close( |
| phNxpEseProto7816SecureTimer_t* pSecureTimerParams) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| if (phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState != |
| PH_NXP_ESE_PROTO_7816_IDLE) |
| return status; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_DEINIT; |
| phNxpEseProto7816_3_Var.recoveryCounter = 0; |
| phNxpEseProto7816_3_Var.wtx_counter = 0; |
| /* send the end of session s-frame */ |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.sFrameType = |
| PROP_END_APDU_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.len = |
| PH_PROTO_7816_VALUE_ZERO; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = SEND_S_EOS; |
| status = TransceiveProcess(); |
| if (ESESTATUS_SUCCESS != status) { |
| /* reset all the structures */ |
| ALOGE("%s TransceiveProcess failed ", __FUNCTION__); |
| if (status == ESESTATUS_TRANSCEIVE_FAILED && |
| phNxpEseProto7816_3_Var.atrInfo.len > PH_PROTO_7816_VALUE_ZERO) { |
| if (phNxpEseProto7816_3_Var.atrInfo |
| .vendorID[PH_PROTO_ATR_RSP_VENDOR_ID_LEN - 1] < |
| PH_SE_OS_VERSION_10) { |
| ALOGD_IF(ese_debug_enabled, "%s shall trigger recovery", __FUNCTION__); |
| status = ESESTATUS_RESPONSE_TIMEOUT; |
| } |
| } |
| } |
| phNxpEse_memcpy(pSecureTimerParams, |
| &phNxpEseProto7816_3_Var.secureTimerParams, |
| sizeof(phNxpEseProto7816SecureTimer_t)); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_IDLE; |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_CloseAllSessions |
| * |
| * Description This function is used to close the 7816 protocol stack |
| *instance |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_CloseAllSessions(void) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| |
| /*Note:- Below OS version check using ATR shall |
| * be removed while integrating with TEE/REE as ATR |
| * information is not available in REE case*/ |
| |
| if (phNxpEseProto7816_3_Var.atrInfo.vendorID[PH_PROTO_ATR_RSP_VENDOR_ID_LEN - |
| 1] >= PH_SE_OS_VERSION_10) { |
| uint8_t* buffer = (uint8_t*)phNxpEse_memalloc(sizeof(uint8_t)); |
| if (buffer != NULL) { |
| buffer[PH_PROTO_7816_VALUE_ZERO] = PH_PROTO_CLOSE_ALL_SESSION_INF; |
| /* send the end of session s-frame */ |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.sFrameType = |
| PROP_END_APDU_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.p_data = buffer; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.len = |
| PH_PROTO_CLOSE_ALL_SESSION_LEN; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_S_EOS; |
| status = TransceiveProcess(); |
| if (ESESTATUS_FAILED == status) { |
| /* reset all the structures */ |
| ALOGD_IF(ese_debug_enabled, "%s EndOfSession failed ", __FUNCTION__); |
| } |
| phNxpEse_free(buffer); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_IDLE; |
| } |
| } else { |
| ALOGD_IF(ese_debug_enabled, "%s Function not supported ", __FUNCTION__); |
| status = ESESTATUS_SUCCESS; |
| } |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_IntfReset |
| * |
| * Description This function is used to reset just the current interface |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_IntfReset( |
| phNxpEseProto7816SecureTimer_t* pSecureTimerParam) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_TRANSCEIVE; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.sFrameType = |
| INTF_RESET_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_S_INTF_RST; |
| status = TransceiveProcess(); |
| if (ESESTATUS_FAILED == status) { |
| /* reset all the structures */ |
| ALOGE("%s TransceiveProcess failed ", __FUNCTION__); |
| } |
| phNxpEse_memcpy(pSecureTimerParam, &phNxpEseProto7816_3_Var.secureTimerParams, |
| sizeof(phNxpEseProto7816SecureTimer_t)); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_IDLE; |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_SetIfs |
| * |
| * Description This function is used to set IFSD value to card |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_SetIfs(uint16_t IFS_Size) { |
| // phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.maxDataLenIFSC = |
| // IFSC_Size; |
| ESESTATUS status = ESESTATUS_FAILED; |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| /* IFSD > IFSC not allowed, card will reject by R-NACK so not sending */ |
| if (IFS_Size > |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.maxDataLenIFSC) { |
| phNxpEseProto7816_3_Var.currentIFSDSize = |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.maxDataLenIFSC; |
| /* IFSD is greater than IFSC , set max IFSC as IFSD*/ |
| ALOGD_IF(ese_debug_enabled, |
| "%s : IFSD greater than IFSC , set max IFSC as IFSD ", |
| __FUNCTION__); |
| } else { |
| phNxpEseProto7816_3_Var.currentIFSDSize = IFS_Size; |
| } |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_TRANSCEIVE; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.sFrameType = IFS_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_S_IFS_ADJ; |
| status = TransceiveProcess(); |
| if (ESESTATUS_FAILED == status) { |
| /* reset all the structures */ |
| ALOGE("%s TransceiveProcess failed ", __FUNCTION__); |
| } |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_IDLE; |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_GetIfs |
| * |
| * Description This function is used to get current IFS adjusted value wrt |
| *card |
| * |
| * Returns On success return true or else false. |
| * |
| ******************************************************************************/ |
| uint16_t phNxpEseProto7816_GetIfs(void) { |
| ALOGD_IF( |
| ese_debug_enabled, "Enter %s current IFSC = %d", __FUNCTION__, |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo.currentDataLenIFS); |
| return phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.IframeInfo |
| .currentDataLenIFS; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_GetOsMode |
| * |
| * Description This function is used to get current OS Mode |
| * |
| * Returns 0x01 : JCOP_MODE |
| * 0x02 : OSU_MODE |
| * |
| ******************************************************************************/ |
| phNxpEseProto7816_OsType_t phNxpEseProto7816_GetOsMode(void) { |
| phNxpEseProto7816_OsType_t mode = UNKNOWN_MODE; |
| if (GET_CHIP_OS_VERSION() >= OS_VERSION_5_2_2) { |
| if (phNxpEseProto7816_3_Var.extndAtrInfo.osType == MODE_JCOP) { |
| ALOGD_IF(ese_debug_enabled, "Enter %s OS Mode = %s", __FUNCTION__, |
| "JCOP Mode"); |
| mode = JCOP_MODE; |
| } else if (phNxpEseProto7816_3_Var.extndAtrInfo.osType == MODE_OSU) { |
| ALOGD_IF(ese_debug_enabled, "Enter %s OS Mode = %s", __FUNCTION__, |
| "OSU Mode"); |
| mode = OSU_MODE; |
| } else { |
| ALOGD_IF(ese_debug_enabled, "Enter %s OS Mode = %s", __FUNCTION__, |
| "UNKNOWN Mode"); |
| mode = UNKNOWN_MODE; |
| } |
| } else { |
| ALOGE("%s function not supported", __FUNCTION__); |
| } |
| return mode; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_getAtr |
| * |
| * Description This function is used to get the ATR data from ESE |
| * |
| * Returns On success return true or else false |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_getAtr(phNxpEse_data* pATRRsp) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| |
| ALOGD_IF(ese_debug_enabled, "Enter %s ", __FUNCTION__); |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_TRANSCEIVE; |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.FrameType = SFRAME; |
| |
| phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx.SframeInfo.sFrameType = ATR_REQ; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_nextTransceiveState = |
| SEND_S_ATR_REQ; |
| status = TransceiveProcess(); |
| if (ESESTATUS_FAILED == status) { |
| /* reset all the structures */ |
| ALOGD_IF(ese_debug_enabled, "%s TransceiveProcess failed ", __FUNCTION__); |
| } |
| |
| status = phNxpEse_GetData(&(pATRRsp->len), &(pATRRsp->p_data)); |
| if (ESESTATUS_SUCCESS == status) { |
| ALOGD_IF(ese_debug_enabled, |
| "%s Data successfully received at 7816, packaging to " |
| "send upper layers: DataLen = %d", |
| __FUNCTION__, pATRRsp->len); |
| } else |
| status = ESESTATUS_FAILED; |
| phNxpEseProto7816_3_Var.phNxpEseProto7816_CurrentState = |
| PH_NXP_ESE_PROTO_7816_IDLE; |
| ALOGD_IF(ese_debug_enabled, "Exit %s ", __FUNCTION__); |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_SetEndPoint |
| * |
| * Description This function is used to set end point protocol context |
| * |
| * Returns Always return TRUE (1). |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_SetEndPoint(uint8_t uEndPoint) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| if (uEndPoint == END_POINT_ESE || uEndPoint == END_POINT_EUICC) { |
| phNxpEseProto7816_3_Var = phNxpEseProto7816_ptr[uEndPoint]; |
| status = ESESTATUS_SUCCESS; |
| } else { |
| /*Do nothing return fail*/ |
| } |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_ResetEndPoint |
| * |
| * Description This function is used to set end point protocol context |
| * |
| * Returns Always return TRUE (1). |
| * |
| ******************************************************************************/ |
| ESESTATUS phNxpEseProto7816_ResetEndPoint(uint8_t uEndPoint) { |
| ESESTATUS status = ESESTATUS_FAILED; |
| if (uEndPoint == END_POINT_ESE || uEndPoint == END_POINT_EUICC) { |
| phNxpEseProto7816_ptr[uEndPoint] = phNxpEseProto7816_3_Var; |
| status = ESESTATUS_SUCCESS; |
| } else { |
| /*Do nothing return fail*/ |
| } |
| return status; |
| } |
| |
| /****************************************************************************** |
| * Function phNxpEseProto7816_ResendLastSFrameReq |
| * |
| * Description This function is used to Resend S-Frame on receiving |
| * non S-Frame response |
| * |
| * Returns If last sent Frame is S-Frame |
| * return TRUE(S-Frame) otherwise FALSE(Non-S-Frame). |
| * |
| ******************************************************************************/ |
| static bool phNxpEseProto7816_ResendLastSFrameReq(void) { |
| bool isLastSFrameReq = false; |
| if (phNxpEseProto7816_3_Var.lastSentNonErrorframeType == SFRAME && |
| WTX_RSP != |
| phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx.SframeInfo.sFrameType) { |
| ALOGD_IF(ese_debug_enabled, |
| "%s Unexpected Frame, re-transmitting the previous S-frame", |
| __FUNCTION__); |
| phNxpEse_memcpy(&phNxpEseProto7816_3_Var.phNxpEseNextTx_Cntx, |
| &phNxpEseProto7816_3_Var.phNxpEseLastTx_Cntx, |
| sizeof(phNxpEseProto7816_NextTx_Info_t)); |
| isLastSFrameReq = true; |
| } |
| return isLastSFrameReq; |
| } |
| |
| /** @} */ |