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 64 /* 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 bool_t rf_deactive_cmd = FALSE; 34 static uint8_t rf_deactivate_cmd[] = { 0x21, 0x06, 0x01, 0x03 }; /* discovery */ 35 static uint8_t rf_deactivated_ntf[] = { 0x61, 0x06, 0x02, 0x03, 0x01 }; 36 static uint8_t reset_ntf[] = {0x60, 0x00, 0x06, 0xA0, 0x00, 0xC7, 0xD4, 0x00, 0x00}; 37 38 static uint32_t kovio_timer; 39 40 /************** Kovio functions ***************************************/ 41 42 static NFCSTATUS phNxpNciHal_rf_deactivate(void); 43 44 /******************************************************************************* 45 ** 46 ** Function hal_write_cb 47 ** 48 ** Description Callback function for hal write. 49 ** 50 ** Returns None 51 ** 52 *******************************************************************************/ 53 static void hal_write_cb(void *pContext, phTmlNfc_TransactInfo_t *pInfo) 54 { 55 UNUSED(pContext); 56 UNUSED(pInfo); 57 return; 58 } 59 60 /******************************************************************************* 61 ** 62 ** Function kovio_timer_handler 63 ** 64 ** Description Callback function for kovio timer. 65 ** 66 ** Returns None 67 ** 68 *******************************************************************************/ 69 static void kovio_timer_handler(uint32_t timerId, void *pContext) 70 { 71 UNUSED(timerId); 72 UNUSED(pContext); 73 NXPLOG_NCIHAL_D(">> kovio_timer_handler. Did not receive RF_INTF_ACTIVATED_NTF, Kovio TAG must be removed."); 74 75 phOsalNfc_Timer_Delete(kovio_timer); 76 77 kovio_detected = 0x00; 78 send_to_upper_kovio=0x01; 79 disable_kovio=0x00; 80 /* 81 * send kovio deactivated ntf to upper layer. 82 */ 83 NXPLOG_NCIHAL_D(">> send kovio deactivated ntf to upper layer."); 84 if (nxpncihal_ctrl.p_nfc_stack_data_cback != NULL) 85 { 86 (*nxpncihal_ctrl.p_nfc_stack_data_cback)( 87 sizeof(rf_deactivated_ntf), rf_deactivated_ntf); 88 } 89 return; 90 } 91 92 /******************************************************************************* 93 ** 94 ** Function phNxpNciHal_rf_deactivate 95 ** 96 ** Description Sends rf deactivate cmd to NFCC 97 ** 98 ** Returns NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED 99 ** 100 *******************************************************************************/ 101 static NFCSTATUS phNxpNciHal_rf_deactivate() 102 { 103 NFCSTATUS status = NFCSTATUS_SUCCESS; 104 int cb_data; 105 int retryCnt = 0; 106 107 do 108 { 109 retryCnt++; 110 status = phTmlNfc_Write(rf_deactivate_cmd, 111 sizeof(rf_deactivate_cmd), 112 (pphTmlNfc_TransactCompletionCb_t) &hal_write_cb, &cb_data); 113 } while(status != NFCSTATUS_PENDING && retryCnt <= MAX_WRITE_RETRY); 114 115 if(status != NFCSTATUS_PENDING) 116 { 117 //phNxpNciHal_emergency_recovery(); 118 if (nxpncihal_ctrl.p_nfc_stack_data_cback!= NULL && 119 nxpncihal_ctrl.hal_open_status == TRUE) 120 { 121 NXPLOG_NCIHAL_D("Send the Core Reset NTF to upper layer, which will trigger the recovery\n"); 122 //Send the Core Reset NTF to upper layer, which will trigger the recovery. 123 send_to_upper_kovio = 0; 124 nxpncihal_ctrl.rx_data_len = sizeof(reset_ntf); 125 memcpy(nxpncihal_ctrl.p_rx_data, reset_ntf, sizeof(reset_ntf)); 126 (*nxpncihal_ctrl.p_nfc_stack_data_cback)(nxpncihal_ctrl.rx_data_len, nxpncihal_ctrl.p_rx_data); 127 } 128 } 129 130 return status; 131 } 132 133 /******************************************************************************* 134 ** 135 ** Function phNxpNciHal_kovio_rsp_ext 136 ** 137 ** Description Implements kovio presence check. In BCM controller this is 138 ** managed by NFCC. But since PN54X does not handle this, the 139 ** presence check is mimiced here. 140 ** For the very first time Kovio is detected, NTF has to be 141 ** passed on to upper layer. for every NTF, DH send a deactivated 142 ** command to NFCC and NFCC follows this up with another activated 143 ** notification. When the tag is removed, activated notification 144 ** stops coming and this is indicated to upper layer with a HAL 145 ** generated deactivated notification. 146 ** Returns NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED 147 ** 148 *******************************************************************************/ 149 NFCSTATUS phNxpNciHal_kovio_rsp_ext(uint8_t *p_ntf, uint16_t *p_len) 150 { 151 NFCSTATUS status = NFCSTATUS_SUCCESS; 152 uint8_t tBuff[KOVIO_ACT_NTF_TEMP_BUFF_LEN]; 153 154 send_to_upper_kovio = 1; 155 if((p_ntf[0]==0x61)&&(p_ntf[1]==0x05)) 156 { 157 #if(NFC_NXP_CHIP_TYPE != PN547C2) 158 if((p_ntf[5]==0x81)&&(p_ntf[6]==0x70)) 159 #else 160 if((p_ntf[5]==0x8A)&&(p_ntf[6]==0x77)) 161 #endif 162 { 163 if (kovio_detected == 0) 164 { 165 if((*p_len-9)<KOVIO_ACT_NTF_TEMP_BUFF_LEN) 166 { 167 p_ntf[2]+=1; 168 memcpy(tBuff, &p_ntf[9], *p_len-9); 169 p_ntf[9]=p_ntf[9]+1; 170 memcpy(&p_ntf[10], tBuff, *p_len-9); 171 *p_len+=1; 172 }else 173 { 174 NXPLOG_NCIHAL_D("Kovio Act ntf payload exceeded temp buffer size"); 175 } 176 kovio_detected = 1; 177 kovio_timer = phOsalNfc_Timer_Create(); 178 NXPLOG_NCIHAL_D("custom kovio timer Created - %d", kovio_timer); 179 } 180 else 181 { 182 send_to_upper_kovio = 0; 183 } 184 185 if (!rf_deactive_cmd) 186 { 187 NXPLOG_NCIHAL_D ("Send RF deactivate command to NFCC"); 188 status = phNxpNciHal_rf_deactivate (); 189 } 190 else 191 { 192 NXPLOG_NCIHAL_D ("RF deactivate command is already sent to NFCC"); 193 disable_kovio = TRUE; 194 send_to_upper_kovio = 0; 195 } 196 status = phOsalNfc_Timer_Start(kovio_timer, 197 KOVIO_TIMEOUT, 198 &kovio_timer_handler, 199 NULL); 200 if (NFCSTATUS_SUCCESS == status) 201 { 202 NXPLOG_NCIHAL_D("kovio timer started"); 203 } 204 else 205 { 206 NXPLOG_NCIHAL_E("kovio timer not started!!!"); 207 status = NFCSTATUS_FAILED; 208 } 209 } 210 else 211 { 212 if (kovio_detected == 1) 213 { 214 phNxpNciHal_clean_Kovio_Ext(); 215 NXPLOG_NCIHAL_D ("Disabling Kovio detection logic as another tag type detected"); 216 } 217 } 218 } 219 else if((p_ntf[0]==0x41)&&(p_ntf[1]==0x06)&&(p_ntf[2]==0x01)) 220 { 221 rf_deactive_cmd = FALSE; 222 if(kovio_detected == 1) 223 send_to_upper_kovio = 0; 224 if((kovio_detected == 1)&&(disable_kovio==0x01)) 225 { 226 NXPLOG_NCIHAL_D ("Disabling Kovio detection logic"); 227 phNxpNciHal_clean_Kovio_Ext(); 228 disable_kovio=0x00; 229 } 230 } 231 else if((p_ntf[0]==0x61)&&(p_ntf[1]==0x06)&&(p_ntf[2]==0x02)&&(p_ntf[3]==0x03)&&(p_ntf[4]==0x00)) 232 { 233 if(kovio_detected == 1) 234 send_to_upper_kovio = 0; 235 } 236 else if((p_ntf[0]==0x61)&&(p_ntf[1]==0x03)) 237 { 238 if(kovio_detected == 1) 239 send_to_upper_kovio = 0; 240 } 241 return status; 242 } 243 /******************************************************************************* 244 ** 245 ** Function phNxpNciHal_clean_Kovio_Ext 246 ** 247 ** Description Clean up Kovio extension state machine. 248 ** Returns NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED 249 ** 250 *******************************************************************************/ 251 void phNxpNciHal_clean_Kovio_Ext() 252 { 253 NXPLOG_NCIHAL_D(">> Cleaning up Kovio State machine and timer."); 254 phOsalNfc_Timer_Delete(kovio_timer); 255 kovio_detected = 0x00; 256 send_to_upper_kovio=0x01; 257 disable_kovio=0x00; 258 /* 259 * send kovio deactivated ntf to upper layer. 260 */ 261 NXPLOG_NCIHAL_D(">> send kovio deactivated ntf to upper layer."); 262 if (nxpncihal_ctrl.p_nfc_stack_data_cback != NULL) 263 { 264 (*nxpncihal_ctrl.p_nfc_stack_data_cback)( 265 sizeof(rf_deactivated_ntf), rf_deactivated_ntf); 266 } 267 return; 268 } 269