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(¤t_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(¤t_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(¤t_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(¤t_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(¤t_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