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