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 *******************************************************************************/
hal_write_cb(void * pContext,phTmlNfc_TransactInfo_t * pInfo)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 *******************************************************************************/
kovio_timer_handler(uint32_t timerId,void * pContext)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 *******************************************************************************/
phNxpNciHal_rf_deactivate()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 *******************************************************************************/
phNxpNciHal_kovio_rsp_ext(uint8_t * p_ntf,uint16_t * p_len)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 *******************************************************************************/
phNxpNciHal_clean_Kovio_Ext()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