1 /******************************************************************************
2  *
3  *  Copyright 2018 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 extern bool ese_debug_enabled;
34 
35 static void* pEseDeviceHandle = NULL;
36 #define MAX_ESE_ACCESS_TIME_OUT_MS 2000 /*2 seconds*/
37 
38 /**
39  * \addtogroup SPI_Power_Management
40  *
41  * @{ */
42 /******************************************************************************
43 \section Introduction Introduction
44 
45  * This module provide power request to Pn54x nfc-i2c driver, it cheks if
46  * wired access is already granted. It should have access to pn54x drive.
47  * Below are the apis provided by the SPM module.
48  ******************************************************************************/
49 /******************************************************************************
50  * Function         phNxpEse_SPM_Init
51  *
52  * Description      This function opens the nfc i2c driver to manage power
53  *                  and synchronization for ese secure element.
54  *
55  * Returns          On Success ESESTATUS_SUCCESS else proper error code
56  *
57  ******************************************************************************/
phNxpEse_SPM_Init(void * pDevHandle)58 ESESTATUS phNxpEse_SPM_Init(void* pDevHandle) {
59   ESESTATUS status = ESESTATUS_SUCCESS;
60   pEseDeviceHandle = pDevHandle;
61   if (NULL == pEseDeviceHandle) {
62     ALOGE("%s : failed, device handle is null", __FUNCTION__);
63     status = ESESTATUS_FAILED;
64   }
65   ALOGD_IF(ese_debug_enabled, "%s : exit status = %d", __FUNCTION__, status);
66 
67   return status;
68 }
69 
70 /******************************************************************************
71  * Function         phNxpEse_SPM_DeInit
72  *
73  * Description      This function closes the nfc i2c driver node.
74  *
75  * Returns          Always returns ESESTATUS_SUCCESS
76  *
77  ******************************************************************************/
phNxpEse_SPM_DeInit(void)78 ESESTATUS phNxpEse_SPM_DeInit(void) {
79   pEseDeviceHandle = NULL;
80   return ESESTATUS_SUCCESS;
81 }
82 
83 /******************************************************************************
84  * Function         phNxpEse_SPM_ConfigPwr
85  *
86  * Description      This function request to the nfc i2c driver
87  *                  to enable/disable power to ese. This api should be called
88  *before
89  *                  sending any apdu to ese/once apdu exchange is done.
90  *
91  * Returns          On Success ESESTATUS_SUCCESS else proper error code
92  *
93  ******************************************************************************/
phNxpEse_SPM_ConfigPwr(spm_power_t arg)94 ESESTATUS phNxpEse_SPM_ConfigPwr(spm_power_t arg) {
95   int32_t ret = -1;
96   ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
97   spm_state_t current_spm_state = SPM_STATE_INVALID;
98 
99   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, arg);
100   switch (arg) {
101     case SPM_POWER_DISABLE: {
102       if (ret < 0) {
103         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
104         wSpmStatus = ESESTATUS_FAILED;
105       }
106     } break;
107     case SPM_POWER_ENABLE: {
108       if (ret < 0) {
109         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
110         if (errno == -EBUSY) {
111           wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
112           if (wSpmStatus != ESESTATUS_SUCCESS) {
113             ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
114             return wSpmStatus;
115           } else {
116             if (current_spm_state & SPM_STATE_DWNLD) {
117               wSpmStatus = ESESTATUS_DWNLD_BUSY;
118             } else {
119               wSpmStatus = ESESTATUS_BUSY;
120             }
121           }
122 
123         } else {
124           wSpmStatus = ESESTATUS_FAILED;
125         }
126       }
127     } break;
128     case SPM_POWER_RESET: {
129       if (ret < 0) {
130         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
131         if (errno == -EBUSY) {
132           wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
133           if (wSpmStatus != ESESTATUS_SUCCESS) {
134             ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
135             return wSpmStatus;
136           } else {
137             if (current_spm_state & SPM_STATE_DWNLD) {
138               wSpmStatus = ESESTATUS_DWNLD_BUSY;
139             } else {
140               wSpmStatus = ESESTATUS_BUSY;
141             }
142           }
143         } else {
144           wSpmStatus = ESESTATUS_FAILED;
145         }
146       }
147     } break;
148     case SPM_POWER_PRIO_ENABLE: {
149       if (ret < 0) {
150         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
151         if (errno == -EBUSY) {
152           wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
153           if (wSpmStatus != ESESTATUS_SUCCESS) {
154             ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
155             return wSpmStatus;
156           } else {
157             if (current_spm_state & SPM_STATE_DWNLD) {
158               wSpmStatus = ESESTATUS_DWNLD_BUSY;
159             } else {
160               wSpmStatus = ESESTATUS_BUSY;
161             }
162           }
163 
164         } else {
165           wSpmStatus = ESESTATUS_FAILED;
166         }
167       }
168     } break;
169     case SPM_POWER_PRIO_DISABLE: {
170       if (ret < 0) {
171         ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
172         wSpmStatus = ESESTATUS_FAILED;
173       }
174     } break;
175   }
176   return wSpmStatus;
177 }
178 
179 /******************************************************************************
180  * Function         phNxpEse_SPM_EnablePwr
181  *
182  * Description      This function request to the nfc i2c driver
183  *                  to enable power to ese. This api should be called before
184  *                  sending any apdu to ese.
185  *
186  * Returns          On Success ESESTATUS_SUCCESS else proper error code
187  *
188  ******************************************************************************/
phNxpEse_SPM_EnablePwr(void)189 ESESTATUS phNxpEse_SPM_EnablePwr(void) {
190   int32_t ret = -1;
191   ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
192   spm_state_t current_spm_state = SPM_STATE_INVALID;
193   ALOGD_IF(ese_debug_enabled, "%s : phNxpEse_SPM_EnablePwr is set to  = 0x%d",
194            __FUNCTION__, 0);
195   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 0);
196   if (ret < 0) {
197     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
198     if (errno == -EBUSY) {
199       wSpmStatus = phNxpEse_SPM_GetState(&current_spm_state);
200       if (wSpmStatus != ESESTATUS_SUCCESS) {
201         ALOGE(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
202         return wSpmStatus;
203       } else {
204         if (current_spm_state == SPM_STATE_DWNLD) {
205           wSpmStatus = ESESTATUS_DWNLD_BUSY;
206         } else {
207           wSpmStatus = ESESTATUS_BUSY;
208         }
209       }
210 
211     } else {
212       wSpmStatus = ESESTATUS_FAILED;
213     }
214   }
215 
216   return wSpmStatus;
217 }
218 
219 /******************************************************************************
220  * Function         phNxpEse_SPM_DisablePwr
221  *
222  * Description      This function request to the nfc i2c driver
223  *                  to disable power to ese. This api should be called
224  *                  once apdu exchange is done.
225  *
226  * Returns          On Success ESESTATUS_SUCCESS else proper error code
227  *
228  ******************************************************************************/
phNxpEse_SPM_DisablePwr(void)229 ESESTATUS phNxpEse_SPM_DisablePwr(void) {
230   int32_t ret = -1;
231   ESESTATUS status = ESESTATUS_SUCCESS;
232   ALOGD_IF(ese_debug_enabled, "%s : phNxpEse_SPM_DisablePwr is set to  = 0x%d",
233            __FUNCTION__, 1);
234   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 1);
235   if (ret < 0) {
236     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
237     status = ESESTATUS_FAILED;
238   }
239 
240   return status;
241 }
242 /******************************************************************************
243  * Function         phNxpEse_SPM_SetPwrScheme
244  *
245  * Description      This function request to the nfc i2c driver
246  *                  to set the chip type and power scheme.
247  *
248  * Returns          On Success ESESTATUS_SUCCESS else proper error code
249  *
250  ******************************************************************************/
phNxpEse_SPM_SetPwrScheme(long arg)251 ESESTATUS phNxpEse_SPM_SetPwrScheme(long arg) {
252   int32_t ret = -1;
253   ESESTATUS status = ESESTATUS_SUCCESS;
254 
255   ALOGD_IF(ese_debug_enabled, "%s : Power scheme is set to  = 0x%ld",
256            __FUNCTION__, arg);
257   ret = phPalEse_ioctl(phPalEse_e_SetPowerScheme, pEseDeviceHandle, arg);
258   if (ret < 0) {
259     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
260     status = ESESTATUS_FAILED;
261   }
262 
263   return status;
264 }
265 
266 /******************************************************************************
267  * Function         phNxpEseP61_SPM_EnableDisablePwrCntrl
268  *
269  * Description      This function request to the nfc i2c driver
270  *                  to set the chip type and power scheme.
271  *
272  * Returns          On Success ESESTATUS_SUCCESS else proper error code
273  *
274  ******************************************************************************/
phNxpEse_SPM_DisablePwrControl(unsigned long arg)275 ESESTATUS phNxpEse_SPM_DisablePwrControl(unsigned long arg) {
276   int32_t ret = -1;
277   ESESTATUS status = ESESTATUS_SUCCESS;
278 
279   ALOGD_IF(ese_debug_enabled, "%s : Inhibit power control is set to  = 0x%ld",
280            __FUNCTION__, arg);
281   ret = phPalEse_ioctl(phPalEse_e_DisablePwrCntrl, pEseDeviceHandle, arg);
282   if (ret < 0) {
283     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
284     status = ESESTATUS_FAILED;
285   }
286 
287   return status;
288 }
289 
290 /******************************************************************************
291  * Function         phNxpEse_SPM_GetState
292  *
293  * Description      This function gets the current power state of ESE
294  *
295  * Returns          On Success ESESTATUS_SUCCESS else proper error code
296  *
297  ******************************************************************************/
phNxpEse_SPM_GetState(spm_state_t * current_state)298 ESESTATUS phNxpEse_SPM_GetState(spm_state_t* current_state) {
299   int32_t ret = -1;
300   ESESTATUS status = ESESTATUS_SUCCESS;
301   spm_state_t ese_current_state = SPM_STATE_INVALID;
302 
303   if (current_state == NULL) {
304     ALOGE("%s : failed Invalid argument", __FUNCTION__);
305     return ESESTATUS_FAILED;
306   }
307   ret = phPalEse_ioctl(phPalEse_e_GetSPMStatus, pEseDeviceHandle,
308                        (unsigned long)&ese_current_state);
309   if (ret < 0) {
310     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
311     status = ESESTATUS_FAILED;
312   } else {
313     *current_state = ese_current_state; /* Current ESE state */
314   }
315 
316   return status;
317 }
318 #ifdef NXP_ESE_JCOP_DWNLD_PROTECTION
319 /******************************************************************************
320  * Function         phNxpEse_SPM_SetJcopDwnldState
321  *
322  * Description      This function is used to set the JCOP OS download state
323  *
324  * Returns          On Success ESESTATUS_SUCCESS else proper error code
325  *
326  ******************************************************************************/
phNxpEse_SPM_SetJcopDwnldState(long arg)327 ESESTATUS phNxpEse_SPM_SetJcopDwnldState(long arg) {
328   int ret = -1;
329   ESESTATUS status = ESESTATUS_SUCCESS;
330 
331   ALOGD_IF(ese_debug_enabled, "%s :phNxpEse_SPM_SetJcopDwnldState  = 0x%ld",
332            __FUNCTION__, arg);
333   ret = phPalEse_ioctl(phPalEse_e_SetJcopDwnldState, pEseDeviceHandle, arg);
334   if (ret < 0) {
335     ALOGE("%s : failed errno = 0x%x", __FUNCTION__, errno);
336     status = ESESTATUS_FAILED;
337   }
338 
339   return status;
340 }
341 #endif