1 /* 2 * Copyright (C) 2012-2014 NXP Semiconductors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <phNxpNciHal_Kovio.h> 18 #include <phNxpLog.h> 19 20 21 #define KOVIO_TIMEOUT 1000 /* Timeout value to wait for RF INTF Activated NTF.*/ 22 #define KOVIO_ACT_NTF_TEMP_BUFF_LEN 32 /* length of temp buffer to manipulate 23 the activated notification to match BCM format*/ 24 #define MAX_WRITE_RETRY 5 25 26 /******************* Global variables *****************************************/ 27 extern phNxpNciHal_Control_t nxpncihal_ctrl; 28 extern NFCSTATUS phNxpNciHal_send_ext_cmd(uint16_t cmd_len, uint8_t *p_cmd); 29 30 int kovio_detected = 0x00; 31 int send_to_upper_kovio = 0x01; 32 int disable_kovio=0x00; 33 static uint8_t rf_deactivate_cmd[] = { 0x21, 0x06, 0x01, 0x03 }; /* discovery */ 34 static uint8_t rf_deactivated_ntf[] = { 0x61, 0x06, 0x02, 0x03, 0x01 }; 35 static uint8_t reset_ntf[] = {0x60, 0x00, 0x06, 0xA0, 0x00, 0xC7, 0xD4, 0x00, 0x00}; 36 37 static uint32_t kovio_timer; 38 39 /************** Kovio functions ***************************************/ 40 41 static NFCSTATUS phNxpNciHal_rf_deactivate(void); 42 43 /******************************************************************************* 44 ** 45 ** Function hal_write_cb 46 ** 47 ** Description Callback function for hal write. 48 ** 49 ** Returns None 50 ** 51 *******************************************************************************/ 52 static void hal_write_cb(void *pContext, phTmlNfc_TransactInfo_t *pInfo) 53 { 54 UNUSED(pContext); 55 UNUSED(pInfo); 56 return; 57 } 58 59 /******************************************************************************* 60 ** 61 ** Function kovio_timer_handler 62 ** 63 ** Description Callback function for kovio timer. 64 ** 65 ** Returns None 66 ** 67 *******************************************************************************/ 68 static void kovio_timer_handler(uint32_t timerId, void *pContext) 69 { 70 UNUSED(timerId); 71 UNUSED(pContext); 72 NXPLOG_NCIHAL_D(">> kovio_timer_handler. Did not receive RF_INTF_ACTIVATED_NTF, Kovio TAG must be removed."); 73 74 phOsalNfc_Timer_Delete(kovio_timer); 75 76 kovio_detected = 0x00; 77 send_to_upper_kovio=0x01; 78 disable_kovio=0x00; 79 /* 80 * send kovio deactivated ntf to upper layer. 81 */ 82 NXPLOG_NCIHAL_D(">> send kovio deactivated ntf to upper layer."); 83 if (nxpncihal_ctrl.p_nfc_stack_data_cback != NULL) 84 { 85 (*nxpncihal_ctrl.p_nfc_stack_data_cback)( 86 sizeof(rf_deactivated_ntf), rf_deactivated_ntf); 87 } 88 return; 89 } 90 91 /******************************************************************************* 92 ** 93 ** Function phNxpNciHal_rf_deactivate 94 ** 95 ** Description Sends rf deactivate cmd to NFCC 96 ** 97 ** Returns NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED 98 ** 99 *******************************************************************************/ 100 static NFCSTATUS phNxpNciHal_rf_deactivate() 101 { 102 NFCSTATUS status = NFCSTATUS_SUCCESS; 103 int cb_data; 104 int retryCnt = 0; 105 106 do 107 { 108 retryCnt++; 109 status = phTmlNfc_Write(rf_deactivate_cmd, 110 sizeof(rf_deactivate_cmd), 111 (pphTmlNfc_TransactCompletionCb_t) &hal_write_cb, &cb_data); 112 } while(status != NFCSTATUS_PENDING && retryCnt <= MAX_WRITE_RETRY); 113 114 if(status != NFCSTATUS_PENDING) 115 { 116 //phNxpNciHal_emergency_recovery(); 117 if (nxpncihal_ctrl.p_nfc_stack_data_cback!= NULL && 118 nxpncihal_ctrl.hal_open_status == TRUE) 119 { 120 NXPLOG_NCIHAL_D("Send the Core Reset NTF to upper layer, which will trigger the recovery\n"); 121 //Send the Core Reset NTF to upper layer, which will trigger the recovery. 122 nxpncihal_ctrl.rx_data_len = sizeof(reset_ntf); 123 memcpy(nxpncihal_ctrl.p_rx_data, reset_ntf, sizeof(reset_ntf)); 124 (*nxpncihal_ctrl.p_nfc_stack_data_cback)(nxpncihal_ctrl.rx_data_len, nxpncihal_ctrl.p_rx_data); 125 } 126 } 127 128 return status; 129 } 130 131 /******************************************************************************* 132 ** 133 ** Function phNxpNciHal_kovio_rsp_ext 134 ** 135 ** Description Implements kovio presence check. In BCM controller this is 136 ** managed by NFCC. But since PN54X does not handle this, the 137 ** presence check is mimiced here. 138 ** For the very first time Kovio is detected, NTF has to be 139 ** passed on to upper layer. for every NTF, DH send a deactivated 140 ** command to NFCC and NFCC follows this up with another activated 141 ** notification. When the tag is removed, activated notification 142 ** stops coming and this is indicated to upper layer with a HAL 143 ** generated deactivated notification. 144 ** Returns NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED 145 ** 146 *******************************************************************************/ 147 NFCSTATUS phNxpNciHal_kovio_rsp_ext(uint8_t *p_ntf, uint16_t *p_len) 148 { 149 NFCSTATUS status = NFCSTATUS_SUCCESS; 150 uint8_t tBuff[KOVIO_ACT_NTF_TEMP_BUFF_LEN]; 151 152 send_to_upper_kovio = 1; 153 if((p_ntf[0]==0x61)&&(p_ntf[1]==0x05)) 154 { 155 #if(NFC_NXP_CHIP_TYPE != PN547C2) 156 if((p_ntf[5]==0x81)&&(p_ntf[6]==0x70)) 157 #else 158 if((p_ntf[5]==0x8A)&&(p_ntf[6]==0x77)) 159 #endif 160 { 161 if (kovio_detected == 0) 162 { 163 if((*p_len-9)<KOVIO_ACT_NTF_TEMP_BUFF_LEN) 164 { 165 p_ntf[2]+=1; 166 memcpy(tBuff, &p_ntf[9], *p_len-9); 167 p_ntf[9]=p_ntf[9]+1; 168 memcpy(&p_ntf[10], tBuff, *p_len-9); 169 *p_len+=1; 170 }else 171 { 172 NXPLOG_NCIHAL_D("Kovio Act ntf payload exceeded temp buffer size"); 173 } 174 kovio_detected = 1; 175 kovio_timer = phOsalNfc_Timer_Create(); 176 NXPLOG_NCIHAL_D("custom kovio timer Created - %d", kovio_timer); 177 } 178 else 179 { 180 send_to_upper_kovio = 0; 181 } 182 NXPLOG_NCIHAL_D("Send RF deactivate command to NFCC"); 183 status = phNxpNciHal_rf_deactivate(); 184 status = phOsalNfc_Timer_Start(kovio_timer, 185 KOVIO_TIMEOUT, 186 &kovio_timer_handler, 187 NULL); 188 if (NFCSTATUS_SUCCESS == status) 189 { 190 NXPLOG_NCIHAL_D("kovio timer started"); 191 } 192 else 193 { 194 NXPLOG_NCIHAL_E("kovio timer not started!!!"); 195 status = NFCSTATUS_FAILED; 196 } 197 } 198 else 199 { 200 if (kovio_detected == 1) 201 { 202 phNxpNciHal_clean_Kovio_Ext(); 203 NXPLOG_NCIHAL_D ("Disabling Kovio detection logic as another tag type detected"); 204 } 205 } 206 } 207 else if((p_ntf[0]==0x41)&&(p_ntf[1]==0x06)&&(p_ntf[2]==0x01)&&(p_ntf[3]==0x00)) 208 { 209 if(kovio_detected == 1) 210 send_to_upper_kovio = 0; 211 if((kovio_detected == 1)&&(disable_kovio==0x01)) 212 { 213 NXPLOG_NCIHAL_D ("Disabling Kovio detection logic"); 214 phNxpNciHal_clean_Kovio_Ext(); 215 disable_kovio=0x00; 216 } 217 } 218 else if((p_ntf[0]==0x61)&&(p_ntf[1]==0x06)&&(p_ntf[2]==0x02)&&(p_ntf[3]==0x03)&&(p_ntf[4]==0x00)) 219 { 220 if(kovio_detected == 1) 221 send_to_upper_kovio = 0; 222 } 223 else if((p_ntf[0]==0x61)&&(p_ntf[1]==0x03)) 224 { 225 if(kovio_detected == 1) 226 send_to_upper_kovio = 0; 227 } 228 return status; 229 } 230 /******************************************************************************* 231 ** 232 ** Function phNxpNciHal_clean_Kovio_Ext 233 ** 234 ** Description Clean up Kovio extension state machine. 235 ** Returns NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED 236 ** 237 *******************************************************************************/ 238 void phNxpNciHal_clean_Kovio_Ext() 239 { 240 NXPLOG_NCIHAL_D(">> Cleaning up Kovio State machine and timer."); 241 phOsalNfc_Timer_Delete(kovio_timer); 242 kovio_detected = 0x00; 243 send_to_upper_kovio=0x01; 244 disable_kovio=0x00; 245 /* 246 * send kovio deactivated ntf to upper layer. 247 */ 248 NXPLOG_NCIHAL_D(">> send kovio deactivated ntf to upper layer."); 249 if (nxpncihal_ctrl.p_nfc_stack_data_cback != NULL) 250 { 251 (*nxpncihal_ctrl.p_nfc_stack_data_cback)( 252 sizeof(rf_deactivated_ntf), rf_deactivated_ntf); 253 } 254 return; 255 } 256