1 /******************************************************************************
2  *
3  *  Copyright 2018-2019 NXP
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 #define LOG_TAG "NxpEseHal"
19 #include <log/log.h>
20 
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <phNxpEsePal.h>
24 #include <phNxpEse_Internal.h>
25 #include <sys/ioctl.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include "phNxpEseFeatures.h"
30 #include "phNxpEse_Spm.h"
31 
32 /*********************** Global Variables *************************************/
33 
34 static void* pEseDeviceHandle = NULL;
35 #define MAX_ESE_ACCESS_TIME_OUT_MS 2000 /*2 seconds*/
36 
37 /**
38  * \addtogroup SPI_Power_Management
39  *
40  * @{ */
41 /******************************************************************************
42 \section Introduction Introduction
43 
44  * This module provide power request to Pn54x nfc-i2c driver, it cheks if
45  * wired access is already granted. It should have access to pn54x drive.
46  * Below are the apis provided by the SPM module.
47  ******************************************************************************/
48 /******************************************************************************
49  * Function         phNxpEse_SPM_Init
50  *
51  * Description      This function opens the nfc i2c driver to manage power
52  *                  and synchronization for ese secure element.
53  *
54  * Returns          On Success ESESTATUS_SUCCESS else proper error code
55  *
56  ******************************************************************************/
phNxpEse_SPM_Init(void * pDevHandle)57 ESESTATUS phNxpEse_SPM_Init(void* pDevHandle) {
58   ESESTATUS status = ESESTATUS_SUCCESS;
59   pEseDeviceHandle = pDevHandle;
60   if (NULL == pEseDeviceHandle) {
61     ALOGE("%s : failed, device handle is null", __FUNCTION__);
62     status = ESESTATUS_FAILED;
63   }
64   ALOGD_IF(ese_debug_enabled, "%s : exit status = %d", __FUNCTION__, status);
65 
66   return status;
67 }
68 
69 /******************************************************************************
70  * Function         phNxpEse_SPM_DeInit
71  *
72  * Description      This function closes the nfc i2c driver node.
73  *
74  * Returns          Always returns ESESTATUS_SUCCESS
75  *
76  ******************************************************************************/
phNxpEse_SPM_DeInit(void)77 ESESTATUS phNxpEse_SPM_DeInit(void) {
78   pEseDeviceHandle = NULL;
79   return ESESTATUS_SUCCESS;
80 }
81 
82 /******************************************************************************
83  * Function         phNxpEse_SPM_ConfigPwr
84  *
85  * Description      This function request to the nfc i2c driver
86  *                  to enable/disable power to ese. This api should be called
87  *before
88  *                  sending any apdu to ese/once apdu exchange is done.
89  *
90  * Returns          On Success ESESTATUS_SUCCESS else proper error code
91  *
92  ******************************************************************************/
phNxpEse_SPM_ConfigPwr(spm_power_t arg)93 ESESTATUS phNxpEse_SPM_ConfigPwr(spm_power_t arg) {
94   int32_t ret = -1;
95   ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
96   spm_state_t current_spm_state = SPM_STATE_INVALID;
97   if (GET_CHIP_OS_VERSION() > OS_VERSION_4_0) {
98     /*None of the IOCTLs valid except SPM_RECOVERY_RESET*/
99     if (arg != SPM_RECOVERY_RESET) {
100       return ESESTATUS_SUCCESS;
101     }
102   }
103   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, arg);
104   switch (arg) {
105     case SPM_POWER_DISABLE: {
106       if (ret < 0) {
107         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
108         wSpmStatus = ESESTATUS_FAILED;
109       } else {
110         if (phNxpEse_SPM_RelAccess() != ESESTATUS_SUCCESS) {
111           ALOGE(" %s phNxpEse_SPM_RelAccess : failed \n", __FUNCTION__);
112         }
113       }
114     } break;
115     case SPM_POWER_ENABLE: {
116       if (ret < 0) {
117         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
118         if (errno == -EBUSY) {
119           wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
120           if (wSpmStatus != ESESTATUS_SUCCESS) {
121             ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
122             if (phNxpEse_SPM_RelAccess() != ESESTATUS_SUCCESS) {
123               ALOGE(" %s phNxpEse_SPM_RelAccess : failed \n", __FUNCTION__);
124             }
125             return wSpmStatus;
126           } else {
127             if (current_spm_state & SPM_STATE_DWNLD) {
128               wSpmStatus = ESESTATUS_DWNLD_BUSY;
129             } else {
130               wSpmStatus = ESESTATUS_BUSY;
131             }
132           }
133         } else {
134           wSpmStatus = ESESTATUS_FAILED;
135         }
136         if (wSpmStatus != ESESTATUS_SUCCESS) {
137           if (phNxpEse_SPM_RelAccess() != ESESTATUS_SUCCESS) {
138             ALOGE(" %s phNxpEse_SPM_RelAccess : failed \n", __FUNCTION__);
139           }
140         }
141       }
142     } break;
143     case SPM_POWER_RESET: {
144       if (ret < 0) {
145         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
146         if (errno == -EBUSY) {
147           wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
148           if (wSpmStatus != ESESTATUS_SUCCESS) {
149             ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
150             return wSpmStatus;
151           } else {
152             if (current_spm_state & SPM_STATE_DWNLD) {
153               wSpmStatus = ESESTATUS_DWNLD_BUSY;
154             } else {
155               wSpmStatus = ESESTATUS_BUSY;
156             }
157           }
158         } else {
159           wSpmStatus = ESESTATUS_FAILED;
160         }
161       }
162     } break;
163     case SPM_POWER_PRIO_ENABLE: {
164       if (ret < 0) {
165         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
166         if (errno == -EBUSY) {
167           wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
168           if (wSpmStatus != ESESTATUS_SUCCESS) {
169             ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
170             return wSpmStatus;
171           } else {
172             if (current_spm_state & SPM_STATE_DWNLD) {
173               wSpmStatus = ESESTATUS_DWNLD_BUSY;
174             } else {
175               wSpmStatus = ESESTATUS_BUSY;
176             }
177           }
178 
179         } else {
180           wSpmStatus = ESESTATUS_FAILED;
181         }
182       }
183     } break;
184     case SPM_POWER_PRIO_DISABLE: {
185       if (ret < 0) {
186         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
187         wSpmStatus = ESESTATUS_FAILED;
188       }
189     } break;
190     case SPM_RECOVERY_RESET: {
191     } break;
192   }
193   return wSpmStatus;
194 }
195 
196 /******************************************************************************
197  * Function         phNxpEse_SPM_EnablePwr
198  *
199  * Description      This function request to the nfc i2c driver
200  *                  to enable power to ese. This api should be called before
201  *                  sending any apdu to ese.
202  *
203  * Returns          On Success ESESTATUS_SUCCESS else proper error code
204  *
205  ******************************************************************************/
phNxpEse_SPM_EnablePwr(void)206 ESESTATUS phNxpEse_SPM_EnablePwr(void) {
207   int32_t ret = -1;
208   ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
209   spm_state_t current_spm_state = SPM_STATE_INVALID;
210   ALOGD_IF(ese_debug_enabled, "%s : phNxpEse_SPM_EnablePwr is set to  = 0x%d",
211            __FUNCTION__, 0);
212   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 0);
213   if (ret < 0) {
214     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
215     if (errno == -EBUSY) {
216       wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
217       if (wSpmStatus != ESESTATUS_SUCCESS) {
218         ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
219         return wSpmStatus;
220       } else {
221         if (current_spm_state == SPM_STATE_DWNLD) {
222           wSpmStatus = ESESTATUS_DWNLD_BUSY;
223         } else {
224           wSpmStatus = ESESTATUS_BUSY;
225         }
226       }
227 
228     } else {
229       wSpmStatus = ESESTATUS_FAILED;
230     }
231   }
232 
233   return wSpmStatus;
234 }
235 
236 /******************************************************************************
237  * Function         phNxpEse_SPM_DisablePwr
238  *
239  * Description      This function request to the nfc i2c driver
240  *                  to disable power to ese. This api should be called
241  *                  once apdu exchange is done.
242  *
243  * Returns          On Success ESESTATUS_SUCCESS else proper error code
244  *
245  ******************************************************************************/
phNxpEse_SPM_DisablePwr(void)246 ESESTATUS phNxpEse_SPM_DisablePwr(void) {
247   int32_t ret = -1;
248   ESESTATUS status = ESESTATUS_SUCCESS;
249   ALOGD_IF(ese_debug_enabled, "%s : phNxpEse_SPM_DisablePwr is set to  = 0x%d",
250            __FUNCTION__, 1);
251   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 1);
252   if (ret < 0) {
253     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
254     status = ESESTATUS_FAILED;
255   }
256 
257   return status;
258 }
259 /******************************************************************************
260  * Function         phNxpEse_SPM_SetPwrScheme
261  *
262  * Description      This function request to the nfc i2c driver
263  *                  to set the chip type and power scheme.
264  *
265  * Returns          On Success ESESTATUS_SUCCESS else proper error code
266  *
267  ******************************************************************************/
phNxpEse_SPM_SetPwrScheme(long arg)268 ESESTATUS phNxpEse_SPM_SetPwrScheme(long arg) {
269   int32_t ret = -1;
270   ESESTATUS status = ESESTATUS_SUCCESS;
271 
272   ALOGD_IF(ese_debug_enabled, "%s : Power scheme is set to  = 0x%ld",
273            __FUNCTION__, arg);
274   ret = phPalEse_ioctl(phPalEse_e_SetPowerScheme, pEseDeviceHandle, arg);
275   if (ret < 0) {
276     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
277     status = ESESTATUS_FAILED;
278   }
279 
280   return status;
281 }
282 
283 /******************************************************************************
284  * Function         phNxpEseP61_SPM_EnableDisablePwrCntrl
285  *
286  * Description      This function request to the nfc i2c driver
287  *                  to set the chip type and power scheme.
288  *
289  * Returns          On Success ESESTATUS_SUCCESS else proper error code
290  *
291  ******************************************************************************/
phNxpEse_SPM_DisablePwrControl(unsigned long arg)292 ESESTATUS phNxpEse_SPM_DisablePwrControl(unsigned long arg) {
293   int32_t ret = -1;
294   ESESTATUS status = ESESTATUS_SUCCESS;
295 
296   ALOGD_IF(ese_debug_enabled, "%s : Inhibit power control is set to  = 0x%ld",
297            __FUNCTION__, arg);
298   ret = phPalEse_ioctl(phPalEse_e_DisablePwrCntrl, pEseDeviceHandle, arg);
299   if (ret < 0) {
300     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
301     status = ESESTATUS_FAILED;
302   }
303 
304   return status;
305 }
306 
307 /******************************************************************************
308  * Function         phNxpEse_SPM_GetState
309  *
310  * Description      This function gets the current power state of ESE
311  *
312  * Returns          On Success ESESTATUS_SUCCESS else proper error code
313  *
314  ******************************************************************************/
phNxpEse_SPM_GetState(spm_state_t * current_state)315 ESESTATUS phNxpEse_SPM_GetState(spm_state_t* current_state) {
316   int32_t ret = -1;
317   ESESTATUS status = ESESTATUS_SUCCESS;
318   spm_state_t ese_current_state = SPM_STATE_INVALID;
319 
320   if (current_state == NULL) {
321     ALOGE("%s : failed Invalid argument", __FUNCTION__);
322     return ESESTATUS_FAILED;
323   }
324   ret = phPalEse_ioctl(phPalEse_e_GetSPMStatus, pEseDeviceHandle,
325                        (unsigned long)&ese_current_state);
326   if (ret < 0) {
327     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
328     status = ESESTATUS_FAILED;
329   } else {
330     *current_state = ese_current_state; /* Current ESE state */
331   }
332 
333   return status;
334 }
335 
336 /******************************************************************************
337  * Function         phNxpEse_SPM_SetJcopDwnldState
338  *
339  * Description      This function is used to set the JCOP OS download state
340  *
341  * Returns          On Success ESESTATUS_SUCCESS else proper error code
342  *
343  ******************************************************************************/
phNxpEse_SPM_SetJcopDwnldState(long arg)344 ESESTATUS phNxpEse_SPM_SetJcopDwnldState(long arg) {
345   int ret = -1;
346   ESESTATUS status = ESESTATUS_SUCCESS;
347 
348   ALOGD_IF(ese_debug_enabled, "%s :phNxpEse_SPM_SetJcopDwnldState  = 0x%ld",
349            __FUNCTION__, arg);
350   ret = phPalEse_ioctl(phPalEse_e_SetJcopDwnldState, pEseDeviceHandle, arg);
351   if (ret < 0) {
352     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
353     status = ESESTATUS_FAILED;
354   }
355 
356   return status;
357 }
358 
359 /******************************************************************************
360  * Function         phNxpEse_SPM_SetEseClientUpdateState
361  *
362  * Description      This function is used to set the ese Update state
363  *
364  * Returns          On Success ESESTATUS_SUCCESS else proper error code
365  *
366  ******************************************************************************/
phNxpEse_SPM_SetEseClientUpdateState(long arg)367 ESESTATUS phNxpEse_SPM_SetEseClientUpdateState(long arg) {
368   int ret = -1;
369   ESESTATUS status = ESESTATUS_SUCCESS;
370 
371   ALOGD_IF(ese_debug_enabled,
372            "%s :phNxpEse_SPM_SetEseClientUpdateState  = 0x%ld", __FUNCTION__,
373            arg);
374   ret = phPalEse_ioctl(phPalEse_e_SetClientUpdateState, pEseDeviceHandle, arg);
375   if (ret < 0) {
376     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
377     status = ESESTATUS_FAILED;
378   }
379 
380   return status;
381 }
382 
383 /******************************************************************************
384  * Function         phNxpEse_SPM_ResetPwr
385  *
386  * Description      This function request to the nfc i2c driver
387  *                  to reset ese.
388  *
389  * Returns          On Success ESESTATUS_SUCCESS else proper error code
390  *
391  ******************************************************************************/
phNxpEse_SPM_ResetPwr(void)392 ESESTATUS phNxpEse_SPM_ResetPwr(void) {
393   int32_t ret = -1;
394   ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
395   spm_state_t current_spm_state = SPM_STATE_INVALID;
396 
397   /* reset the ese */
398   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 2);
399   if (ret < 0) {
400     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
401     if (errno == -EBUSY || errno == EBUSY) {
402       wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
403       if (wSpmStatus != ESESTATUS_SUCCESS) {
404         ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
405         return wSpmStatus;
406       } else {
407         if (current_spm_state == SPM_STATE_DWNLD) {
408           wSpmStatus = ESESTATUS_DWNLD_BUSY;
409         } else {
410           wSpmStatus = ESESTATUS_BUSY;
411         }
412       }
413 
414     } else {
415       wSpmStatus = ESESTATUS_FAILED;
416     }
417   }
418 
419   return wSpmStatus;
420 }
421 
422 /*******************************************************************************
423 **
424 ** Function         phTmlEse_get_ese_access
425 **
426 ** Description
427 **
428 ** Parameters       timeout - timeout to wait for ese access
429 **
430 ** Returns          success or failure
431 **
432 *******************************************************************************/
phNxpEse_SPM_GetAccess(long timeout)433 ESESTATUS phNxpEse_SPM_GetAccess(long timeout) {
434   ESESTATUS status = ESESTATUS_SUCCESS;
435   ALOGD_IF(ese_debug_enabled, "phTmlEse_get_ese_access(), timeout  %ld",
436            timeout);
437 #if ((NFC_NXP_ESE_VER == JCOP_VER_3_1) || (NFC_NXP_ESE_VER == JCOP_VER_3_2))
438   int ret = -1;
439 
440   ret = phPalEse_ioctl(phPalEse_e_GetEseAccess, pEseDeviceHandle, timeout);
441   if (ret < 0) {
442     if (ret == -EBUSY)
443       status = ESESTATUS_BUSY;
444     else
445       status = ESESTATUS_FAILED;
446   }
447   ALOGD_IF(ese_debug_enabled, "phTmlEse_get_ese_access(), exit  %d", status);
448 #endif
449   return status;
450 }
451 /*******************************************************************************
452 **
453 ** Function         phNxpEse_SPM_RelAccess
454 **
455 ** Description
456 **
457 ** Parameters       timeout - Releases the ese access
458 **
459 ** Returns          success or failure
460 **
461 *******************************************************************************/
phNxpEse_SPM_RelAccess(void)462 ESESTATUS phNxpEse_SPM_RelAccess(void) {
463   ESESTATUS status = ESESTATUS_SUCCESS;
464 #if ((NFC_NXP_ESE_VER == JCOP_VER_3_1) || (NFC_NXP_ESE_VER == JCOP_VER_3_2))
465   int ret = -1;
466   ALOGD_IF(ese_debug_enabled, "phNxpEse_SPM_RelAccess(): enter");
467 
468   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 5);
469   if (ret < 0) {
470     status = ESESTATUS_FAILED;
471   }
472   ALOGD_IF(ese_debug_enabled, "phNxpEse_SPM_RelAccess(): exit  %d", status);
473 #endif
474   return status;
475 }
476 /** @} */
477