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