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