| /* |
| * Copyright (C) 2012-2014 NXP Semiconductors |
| * |
| * 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. |
| */ |
| |
| #include <phNxpLog.h> |
| #include <phNxpNciHal_Kovio.h> |
| |
| /* Timeout value to wait for RF INTF Activated NTF.*/ |
| #define KOVIO_TIMEOUT 1000 |
| #define KOVIO_ACT_NTF_TEMP_BUFF_LEN \ |
| 64 /* length of temp buffer to manipulate \ |
| the activated notification to match BCM format*/ |
| #define MAX_WRITE_RETRY 5 |
| |
| /******************* Global variables *****************************************/ |
| extern phNxpNciHal_Control_t nxpncihal_ctrl; |
| extern NFCSTATUS phNxpNciHal_send_ext_cmd(uint16_t cmd_len, uint8_t* p_cmd); |
| |
| int kovio_detected = 0x00; |
| int send_to_upper_kovio = 0x01; |
| int disable_kovio = 0x00; |
| bool_t rf_deactive_cmd = false; |
| static uint8_t rf_deactivate_cmd[] = {0x21, 0x06, 0x01, 0x03}; /* discovery */ |
| static uint8_t rf_deactivated_ntf[] = {0x61, 0x06, 0x02, 0x03, 0x01}; |
| static uint8_t reset_ntf[] = {0x60, 0x00, 0x06, 0xA0, 0x00, |
| 0xC7, 0xD4, 0x00, 0x00}; |
| |
| static uint32_t kovio_timer; |
| |
| /************** Kovio functions ***************************************/ |
| |
| static NFCSTATUS phNxpNciHal_rf_deactivate(void); |
| |
| /******************************************************************************* |
| ** |
| ** Function hal_write_cb |
| ** |
| ** Description Callback function for hal write. |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void hal_write_cb(void* pContext, phTmlNfc_TransactInfo_t* pInfo) { |
| UNUSED(pContext); |
| UNUSED(pInfo); |
| return; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function kovio_timer_handler |
| ** |
| ** Description Callback function for kovio timer. |
| ** |
| ** Returns None |
| ** |
| *******************************************************************************/ |
| static void kovio_timer_handler(uint32_t timerId, void* pContext) { |
| UNUSED(timerId); |
| UNUSED(pContext); |
| NXPLOG_NCIHAL_D( |
| ">> kovio_timer_handler. Did not receive RF_INTF_ACTIVATED_NTF, Kovio " |
| "TAG must be removed."); |
| |
| phOsalNfc_Timer_Delete(kovio_timer); |
| |
| kovio_detected = 0x00; |
| send_to_upper_kovio = 0x01; |
| disable_kovio = 0x00; |
| /* |
| * send kovio deactivated ntf to upper layer. |
| */ |
| NXPLOG_NCIHAL_D(">> send kovio deactivated ntf to upper layer."); |
| if (nxpncihal_ctrl.p_nfc_stack_data_cback != NULL) { |
| (*nxpncihal_ctrl.p_nfc_stack_data_cback)(sizeof(rf_deactivated_ntf), |
| rf_deactivated_ntf); |
| } |
| return; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function phNxpNciHal_rf_deactivate |
| ** |
| ** Description Sends rf deactivate cmd to NFCC |
| ** |
| ** Returns NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED |
| ** |
| *******************************************************************************/ |
| static NFCSTATUS phNxpNciHal_rf_deactivate() { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| int cb_data; |
| int retryCnt = 0; |
| |
| do { |
| retryCnt++; |
| status = phTmlNfc_Write(rf_deactivate_cmd, sizeof(rf_deactivate_cmd), |
| (pphTmlNfc_TransactCompletionCb_t)&hal_write_cb, |
| &cb_data); |
| } while (status != NFCSTATUS_PENDING && retryCnt <= MAX_WRITE_RETRY); |
| |
| if (status != NFCSTATUS_PENDING) { |
| // phNxpNciHal_emergency_recovery(); |
| if (nxpncihal_ctrl.p_nfc_stack_data_cback != NULL && |
| nxpncihal_ctrl.hal_open_status == true) { |
| NXPLOG_NCIHAL_D( |
| "Send the Core Reset NTF to upper layer, which will trigger the " |
| "recovery\n"); |
| // Send the Core Reset NTF to upper layer, which will trigger the |
| // recovery. |
| send_to_upper_kovio = 0; |
| nxpncihal_ctrl.rx_data_len = sizeof(reset_ntf); |
| memcpy(nxpncihal_ctrl.p_rx_data, reset_ntf, sizeof(reset_ntf)); |
| (*nxpncihal_ctrl.p_nfc_stack_data_cback)(nxpncihal_ctrl.rx_data_len, |
| nxpncihal_ctrl.p_rx_data); |
| } |
| } |
| |
| return status; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function phNxpNciHal_kovio_rsp_ext |
| ** |
| ** Description Implements kovio presence check. In BCM controller this is |
| ** managed by NFCC. But since PN54X does not handle this, the |
| ** presence check is mimiced here. |
| ** For the very first time Kovio is detected, NTF has to be |
| ** passed on to upper layer. for every NTF, DH send a |
| ** deactivated command to NFCC and NFCC follows this up with |
| ** another activated notification. When the tag is removed, |
| ** activated notification stops coming and this is indicated to |
| ** upper layer with a HAL generated deactivated notification. |
| ** |
| ** Returns NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED |
| ** |
| *******************************************************************************/ |
| NFCSTATUS phNxpNciHal_kovio_rsp_ext(uint8_t* p_ntf, uint16_t* p_len) { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| uint8_t tBuff[KOVIO_ACT_NTF_TEMP_BUFF_LEN]; |
| |
| send_to_upper_kovio = 1; |
| if ((p_ntf[0] == 0x61) && (p_ntf[1] == 0x05)) { |
| #if (NFC_NXP_CHIP_TYPE != PN547C2) |
| if ((p_ntf[5] == 0x81) && (p_ntf[6] == 0x70)) |
| #else |
| if ((p_ntf[5] == 0x8A) && (p_ntf[6] == 0x77)) |
| #endif |
| { |
| if (kovio_detected == 0) { |
| if ((*p_len - 9) < KOVIO_ACT_NTF_TEMP_BUFF_LEN) { |
| p_ntf[2] += 1; |
| memcpy(tBuff, &p_ntf[9], *p_len - 9); |
| p_ntf[9] = p_ntf[9] + 1; |
| memcpy(&p_ntf[10], tBuff, *p_len - 9); |
| *p_len += 1; |
| } else { |
| NXPLOG_NCIHAL_D("Kovio Act ntf payload exceeded temp buffer size"); |
| } |
| kovio_detected = 1; |
| kovio_timer = phOsalNfc_Timer_Create(); |
| NXPLOG_NCIHAL_D("custom kovio timer Created - %d", kovio_timer); |
| } else { |
| send_to_upper_kovio = 0; |
| } |
| |
| if (!rf_deactive_cmd) { |
| NXPLOG_NCIHAL_D("Send RF deactivate command to NFCC"); |
| status = phNxpNciHal_rf_deactivate(); |
| } else { |
| NXPLOG_NCIHAL_D("RF deactivate command is already sent to NFCC"); |
| disable_kovio = true; |
| send_to_upper_kovio = 0; |
| } |
| status = phOsalNfc_Timer_Start(kovio_timer, KOVIO_TIMEOUT, |
| &kovio_timer_handler, NULL); |
| if (NFCSTATUS_SUCCESS == status) { |
| NXPLOG_NCIHAL_D("kovio timer started"); |
| } else { |
| NXPLOG_NCIHAL_E("kovio timer not started!!!"); |
| status = NFCSTATUS_FAILED; |
| } |
| } else { |
| if (kovio_detected == 1) { |
| phNxpNciHal_clean_Kovio_Ext(); |
| NXPLOG_NCIHAL_D( |
| "Disabling Kovio detection logic as another tag type detected"); |
| } |
| } |
| } else if ((p_ntf[0] == 0x41) && (p_ntf[1] == 0x06) && (p_ntf[2] == 0x01)) { |
| rf_deactive_cmd = false; |
| if (kovio_detected == 1) send_to_upper_kovio = 0; |
| if ((kovio_detected == 1) && (disable_kovio == 0x01)) { |
| NXPLOG_NCIHAL_D("Disabling Kovio detection logic"); |
| phNxpNciHal_clean_Kovio_Ext(); |
| disable_kovio = 0x00; |
| } |
| } else if ((p_ntf[0] == 0x61) && (p_ntf[1] == 0x06) && (p_ntf[2] == 0x02) && |
| (p_ntf[3] == 0x03) && (p_ntf[4] == 0x00)) { |
| if (kovio_detected == 1) send_to_upper_kovio = 0; |
| } else if ((p_ntf[0] == 0x61) && (p_ntf[1] == 0x03)) { |
| if (kovio_detected == 1) send_to_upper_kovio = 0; |
| } |
| return status; |
| } |
| /******************************************************************************* |
| ** |
| ** Function phNxpNciHal_clean_Kovio_Ext |
| ** |
| ** Description Clean up Kovio extension state machine. |
| ** Returns NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED |
| ** |
| *******************************************************************************/ |
| void phNxpNciHal_clean_Kovio_Ext() { |
| NXPLOG_NCIHAL_D(">> Cleaning up Kovio State machine and timer."); |
| phOsalNfc_Timer_Delete(kovio_timer); |
| kovio_detected = 0x00; |
| send_to_upper_kovio = 0x01; |
| disable_kovio = 0x00; |
| /* |
| * send kovio deactivated ntf to upper layer. |
| */ |
| NXPLOG_NCIHAL_D(">> send kovio deactivated ntf to upper layer."); |
| if (nxpncihal_ctrl.p_nfc_stack_data_cback != NULL) { |
| (*nxpncihal_ctrl.p_nfc_stack_data_cback)(sizeof(rf_deactivated_ntf), |
| rf_deactivated_ntf); |
| } |
| return; |
| } |