1 /******************************************************************************
2  *
3  *  Copyright 2018-2020 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 
19 /*
20  * DAL spi port implementation for linux
21  *
22  * Project: Trusted ESE Linux
23  *
24  */
25 
26 #include "EseSpiTransport.h"
27 
28 #define LOG_TAG "NxpEseHal"
29 #include <log/log.h>
30 
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <sys/ioctl.h>
35 #include <unistd.h>
36 
37 #include <ese_config.h>
38 #include <hardware/nfc.h>
39 #include <phEseStatus.h>
40 #include <phNxpEsePal.h>
41 #include <string.h>
42 #include "NfcAdaptation.h"
43 #include "hal_nxpese.h"
44 #include "phNxpEse_Api.h"
45 
46 #define MAX_RETRY_CNT 10
47 #define HAL_NFC_SPI_DWP_SYNC 21
48 
49 extern int omapi_status;
50 
51 static int rf_status;
52 #if (NFC_NXP_ESE_VER == JCOP_VER_5_x)
53 eseIoctlData_t eseioctldata;
54 #endif
55 // Default max retry count for SPI CLT write blocked in secs
56 static unsigned long int gsMaxSpiWriteRetryCnt = 10;
57 #if (NFC_NXP_ESE_VER == JCOP_VER_4_0)
58 static ESESTATUS phNxpEse_spiIoctl_legacy(uint64_t ioctlType, void* p_data);
59 #endif
60 
61 /*******************************************************************************
62 **
63 ** Function         phPalEse_spi_close
64 **
65 ** Description      Closes PN547 device
66 **
67 ** Parameters       pDevHandle - device handle
68 **
69 ** Returns          None
70 **
71 *******************************************************************************/
Close(void * pDevHandle)72 void EseSpiTransport::Close(void* pDevHandle) {
73   if (NULL != pDevHandle) {
74     close((intptr_t)pDevHandle);
75   }
76   return;
77 }
78 
79 /*******************************************************************************
80 **
81 ** Function         phNxpEse_spiIoctl
82 **
83 ** Description      Perform cross HAL IOCTL functionality
84 **
85 ** Parameters       ioctlType, input data
86 **
87 ** Returns          SUCCESS/FAIL
88 **
89 *******************************************************************************/
phNxpEse_spiIoctl(uint64_t ioctlType,void * p_data)90 ESESTATUS phNxpEse_spiIoctl(uint64_t ioctlType, void* p_data) {
91   ESESTATUS status = ESESTATUS_SUCCESS;
92   if (!p_data) {
93     ALOGE("halimpl phNxpEse_spiIoctl p_data is null ioctltyp: %ld",
94           (long)ioctlType);
95     return ESESTATUS_FAILED;
96   }
97 #if (NFC_NXP_ESE_VER == JCOP_VER_5_x)
98   ese_nxp_IoctlInOutData_t* inpOutData = (ese_nxp_IoctlInOutData_t*)p_data;
99   switch (ioctlType) {
100     case HAL_ESE_IOCTL_RF_STATUS_UPDATE:
101       rf_status = inpOutData->inp.data.nxpCmd.p_cmd[0];
102       if (rf_status == 1) {
103         ALOGD_IF(
104             ese_debug_enabled,
105             "******************RF IS ON*************************************");
106       } else {
107         ALOGD_IF(
108             ese_debug_enabled,
109             "******************RF IS OFF*************************************");
110       }
111       break;
112     case HAL_ESE_IOCTL_NFC_JCOP_DWNLD:
113 
114       eseioctldata.nfc_jcop_download_state =
115           inpOutData->inp.data.nxpCmd.p_cmd[0];
116       if (eseioctldata.nfc_jcop_download_state == 1) {
117         ALOGD_IF(ese_debug_enabled,
118                  "******************JCOP Download "
119                  "started*************************************");
120       } else {
121         ALOGD_IF(ese_debug_enabled,
122                  "******************JCOP Download "
123                  "stopped*************************************");
124       }
125       break;
126     default:
127       ALOGD_IF(ese_debug_enabled, "Invalid IOCTL type");
128       break;
129   }
130 #endif
131 #if (NFC_NXP_ESE_VER == JCOP_VER_4_0)
132   status = phNxpEse_spiIoctl_legacy(ioctlType, p_data);
133 #endif
134   return status;
135 }
136 #if (NFC_NXP_ESE_VER == JCOP_VER_4_0)
137 /*******************************************************************************
138 **
139 ** Function         phNxpEse_spiIoctl_legacy
140 **
141 ** Description      Perform cross HAL IOCTL functionality
142 **
143 ** Parameters       ioctlType, input data
144 **
145 ** Returns          SUCCESS/FAIL
146 **
147 *******************************************************************************/
phNxpEse_spiIoctl_legacy(uint64_t ioctlType,void * p_data)148 static ESESTATUS phNxpEse_spiIoctl_legacy(uint64_t ioctlType, void* p_data) {
149   ese_nxp_IoctlInOutData_t* inpOutData = (ese_nxp_IoctlInOutData_t*)p_data;
150   switch (ioctlType) {
151     case HAL_ESE_IOCTL_RF_STATUS_UPDATE:
152 
153       rf_status = inpOutData->inp.data.nxpCmd.p_cmd[0];
154       if (rf_status == 1) {
155         ALOGD_IF(
156             ese_debug_enabled,
157             "******************RF IS ON*************************************");
158       } else {
159         ALOGD_IF(
160             ese_debug_enabled,
161             "******************RF IS OFF*************************************");
162       }
163       break;
164     default:
165       ALOGD_IF(ese_debug_enabled, "Invalid IOCTL type");
166       break;
167   }
168   return ESESTATUS_SUCCESS;
169 }
170 #endif
171 
172 /*******************************************************************************
173 **
174 ** Function         OpenAndConfigure
175 **
176 ** Description      Open and configure pn547 device
177 **
178 ** Parameters       pConfig     - hardware information
179 **                  pLinkHandle - device handle
180 **
181 ** Returns          ESE status:
182 **                  ESESTATUS_SUCCESS            - open_and_configure operation
183 *success
184 **                  ESESTATUS_INVALID_DEVICE     - device open operation failure
185 **
186 *******************************************************************************/
OpenAndConfigure(pphPalEse_Config_t pConfig)187 ESESTATUS EseSpiTransport::OpenAndConfigure(pphPalEse_Config_t pConfig) {
188   int nHandle;
189   int retryCnt = 0;
190   ALOGD("NxpEse EseSpiTransport::OpenAndConfigure 1");
191   if (EseConfig::hasKey(NAME_NXP_SOF_WRITE)) {
192     mConfigSofWrite = EseConfig::getUnsigned(NAME_NXP_SOF_WRITE);
193     ALOGD_IF(ese_debug_enabled, "NXP_SOF_WRITE value from config file = %ld",
194              mConfigSofWrite);
195   }
196   if (EseConfig::hasKey(NAME_NXP_SPI_WRITE_TIMEOUT)) {
197     mConfigSpiWriteTimeout = EseConfig::getUnsigned(NAME_NXP_SPI_WRITE_TIMEOUT);
198     ALOGD_IF(ese_debug_enabled,
199              "NXP_SPI_WRITE_TIMEOUT value from config file = %ld",
200              mConfigSpiWriteTimeout);
201   }
202   /* Read eSE cold reset interface from ese config file */
203   if (EseConfig::hasKey(NAME_NXP_P61_COLD_RESET_INTERFACE)) {
204     mConfigColdResetIntf =
205         EseConfig::getUnsigned(NAME_NXP_P61_COLD_RESET_INTERFACE);
206     ALOGD_IF(ese_debug_enabled,
207              "mConfigColdResetIntf value from config file = %ld",
208              mConfigColdResetIntf);
209   } else {
210     mConfigColdResetIntf = 0x01; /* Default interface is NFC HAL */
211     ALOGD_IF(ese_debug_enabled, "mConfigColdResetIntf: Default value ");
212   }
213   ALOGD_IF(ese_debug_enabled, "Opening port=%s\n", pConfig->pDevName);
214 /* open port */
215 retry:
216   nHandle = open((char const*)pConfig->pDevName, O_RDWR);
217   if (nHandle < 0) {
218     ALOGE("%s : failed errno = 0x%x, retval %x", __FUNCTION__, errno, nHandle);
219 
220     if ((errno == -EBUSY) || (errno == EBUSY)) {
221       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
222         phPalEse_sleep(100 * 1000);  // 100ms delay
223         return ESESTATUS_DRIVER_BUSY;
224       } else {
225         retryCnt++;
226         ALOGE("Retry open eSE driver, retry cnt : %d", retryCnt);
227         if (retryCnt < MAX_RETRY_CNT) {
228           phPalEse_sleep(1000000);
229           goto retry;
230         }
231       }
232     }
233     ALOGE("_spi_open() Failed: retval %x", nHandle);
234     pConfig->pDevHandle = NULL;
235     return ESESTATUS_INVALID_DEVICE;
236   }
237   ALOGD_IF(ese_debug_enabled, "eSE driver opened :: fd = [%d]", nHandle);
238   pConfig->pDevHandle = (void*)((intptr_t)nHandle);
239   return ESESTATUS_SUCCESS;
240 }
241 
242 /*******************************************************************************
243 **
244 ** Function         Read
245 **
246 ** Description      Reads requested number of bytes from pn547 device into given
247 *buffer
248 **
249 ** Parameters       pDevHandle       - valid device handle
250 **                  pBuffer          - buffer for read data
251 **                  nNbBytesToRead   - number of bytes requested to be read
252 **
253 ** Returns          numRead   - number of successfully read bytes
254 **                  -1        - read operation failure
255 **
256 *******************************************************************************/
Read(void * pDevHandle,uint8_t * pBuffer,int nNbBytesToRead)257 int EseSpiTransport::Read(void* pDevHandle, uint8_t* pBuffer,
258                           int nNbBytesToRead) {
259   int ret = -1;
260   ret = read((intptr_t)pDevHandle, (void*)pBuffer, (nNbBytesToRead));
261   return ret;
262 }
263 
264 /*******************************************************************************
265 **
266 ** Function         Write
267 **
268 ** Description      Writes requested number of bytes from given buffer into
269 *pn547 device
270 **
271 ** Parameters       pDevHandle       - valid device handle
272 **                  pBuffer          - buffer for read data
273 **                  nNbBytesToWrite  - number of bytes requested to be written
274 **
275 ** Returns          numWrote   - number of successfully written bytes
276 **                  -1         - write operation failure
277 **
278 *******************************************************************************/
Write(void * pDevHandle,uint8_t * pBuffer,int nNbBytesToWrite)279 int EseSpiTransport::Write(void* pDevHandle, uint8_t* pBuffer,
280                            int nNbBytesToWrite) {
281   int ret = -1;
282   int numWrote = 0;
283   unsigned long int retryCount = 0;
284   if (NULL == pDevHandle) {
285     ALOGE("phPalEse_spi_write: received pDevHandle=NULL");
286     return -1;
287   }
288   if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
289     if (mConfigSofWrite == 1) {
290       /* Appending SOF for SPI write */
291       pBuffer[0] = SEND_PACKET_SOF;
292     } else {
293       /* Do Nothing */
294     }
295   }
296   ALOGE("NXP_SPI_WRITE_TIMEOUT value is... : %ld secs", mConfigSpiWriteTimeout);
297   if (mConfigSpiWriteTimeout > 0) {
298     gsMaxSpiWriteRetryCnt = mConfigSpiWriteTimeout;
299     ALOGE(" spi_write_timeout Wait time ... : %ld", gsMaxSpiWriteRetryCnt);
300   } else {
301     /* Do Nothing */
302   }
303 
304   while (numWrote < nNbBytesToWrite) {
305     // usleep(5000);
306     if (rf_status == 0) {
307       ret = write((intptr_t)pDevHandle, pBuffer + numWrote,
308                   nNbBytesToWrite - numWrote);
309     } else {
310       ret = -1;
311     }
312     if (ret > 0) {
313       numWrote += ret;
314     } else if (ret == 0) {
315       ALOGE("_spi_write() EOF");
316       return -1;
317     } else {
318       ALOGE("_spi_write() errno : %x", errno);
319       ALOGD_IF(ese_debug_enabled, "rf_status value is %d", rf_status);
320       if ((errno == EINTR || errno == EAGAIN || rf_status == 1) &&
321           (retryCount < gsMaxSpiWriteRetryCnt)) {
322         /*Configure retry count or timeout here,now its configured for 2*10
323          * secs*/
324         if (retryCount > gsMaxSpiWriteRetryCnt) {
325           ret = -1;
326           break;
327         }
328 
329         retryCount++;
330         /* 5ms delay to give ESE wake up delay */
331         phPalEse_sleep(1000 * (GET_WAKE_UP_DELAY()));
332         ALOGE("_spi_write() failed. Going to retry, counter:%ld !", retryCount);
333         continue;
334       }
335       return -1;
336     }
337   }
338   return numWrote;
339 }
340 
341 /*******************************************************************************
342 **
343 ** Function         Ioctl
344 **
345 ** Description      Exposed ioctl by p61 spi driver
346 **
347 ** Parameters       pDevHandle     - valid device handle
348 **                  level          - reset level
349 **
350 ** Returns           0   - ioctl operation success
351 **                  -1   - ioctl operation failure
352 **
353 *******************************************************************************/
Ioctl(phPalEse_ControlCode_t eControlCode,void * pDevHandle,long level)354 ESESTATUS EseSpiTransport::Ioctl(phPalEse_ControlCode_t eControlCode,
355                                  void* pDevHandle, long level) {
356   ESESTATUS ret = ESESTATUS_IOCTL_FAILED;
357   int retioctl = 0x00;
358 #if (NFC_NXP_ESE_VER == JCOP_VER_5_x)
359   ese_nxp_IoctlInOutData_t inpOutData;
360   inpOutData.inp.level = level;
361   NfcAdaptation& pNfcAdapt = NfcAdaptation::GetInstance();
362 #endif
363   ALOGD_IF(ese_debug_enabled, "phPalEse_spi_ioctl(), ioctl %x , level %lx",
364            eControlCode, level);
365   if (NULL == pDevHandle) {
366     if (GET_CHIP_OS_VERSION() == OS_VERSION_4_0) {
367       return ESESTATUS_IOCTL_FAILED;
368     }
369   }
370   switch (eControlCode) {
371     case phPalEse_e_ResetDevice:
372       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
373         ret = ESESTATUS_SUCCESS;
374       } else {
375         ret = (ESESTATUS)ioctl((intptr_t)pDevHandle, P61_SET_PWR, level);
376       }
377       break;
378 
379     case phPalEse_e_EnableLog:
380       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
381         ret = ESESTATUS_SUCCESS;
382       } else {
383         ret = (ESESTATUS)ioctl((intptr_t)pDevHandle, P61_SET_DBG, level);
384       }
385       break;
386 
387     case phPalEse_e_EnablePollMode:
388       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
389         ret = ESESTATUS_SUCCESS;
390       } else {
391         ret = (ESESTATUS)ioctl((intptr_t)pDevHandle, P61_SET_POLL, level);
392       }
393       break;
394     case phPalEse_e_SetSecureMode:
395       ret =
396           (ESESTATUS)ioctl((intptr_t)pDevHandle, ESE_SET_TRUSTED_ACCESS, level);
397       if (0x00 <= ret) {
398         ret = ESESTATUS_SUCCESS;
399       }
400       break;
401     case phPalEse_e_ChipRst:
402       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
403         if (level == 5) {              // SPI driver communication part
404           if (!mConfigColdResetIntf) { /* Call the driver IOCTL */
405             retioctl =
406                 ioctl((intptr_t)pDevHandle, ESE_PERFORM_COLD_RESET, level);
407             if (0x00 <= retioctl) {
408               ret = ESESTATUS_SUCCESS;
409             }
410           } else {
411 #if (NFC_NXP_ESE_VER == JCOP_VER_5_x)
412             // Nfc Driver communication part
413             ret = pNfcAdapt.resetEse(level);
414 #else
415             ret = ESESTATUS_SUCCESS;
416 #endif
417           }
418         } else {
419           ret = ESESTATUS_SUCCESS;
420         }
421       } else {
422         ret = (ESESTATUS)ioctl((intptr_t)pDevHandle, P61_SET_SPM_PWR, level);
423       }
424       break;
425     case phPalEse_e_ResetProtection:
426       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
427         retioctl = ioctl((intptr_t)pDevHandle, PERFORM_RESET_PROTECTION, level);
428         if (0x00 <= retioctl) {
429           ret = ESESTATUS_SUCCESS;
430         } else {
431           ALOGE("phPalEse_e_ResetProtection ioctl failed status :%x !",
432                 retioctl);
433         }
434       }
435       break;
436     case phPalEse_e_EnableThroughputMeasurement:
437       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
438         ret = ESESTATUS_SUCCESS;
439       } else {
440         ret = (ESESTATUS)ioctl((intptr_t)pDevHandle, P61_SET_THROUGHPUT, level);
441       }
442       break;
443 
444     case phPalEse_e_SetPowerScheme:
445       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
446         ret = ESESTATUS_SUCCESS;
447       } else {
448         ret =
449             (ESESTATUS)ioctl((intptr_t)pDevHandle, P61_SET_POWER_SCHEME, level);
450       }
451       break;
452 
453     case phPalEse_e_GetSPMStatus:
454       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
455         ret = ESESTATUS_SUCCESS;
456       } else {
457         ret = (ESESTATUS)ioctl((intptr_t)pDevHandle, P61_GET_SPM_STATUS, level);
458       }
459       break;
460 
461     case phPalEse_e_GetEseAccess:
462       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
463         ret = ESESTATUS_SUCCESS;
464       } else {
465         ret = (ESESTATUS)ioctl((intptr_t)pDevHandle, P61_GET_ESE_ACCESS, level);
466       }
467       break;
468     case phPalEse_e_SetJcopDwnldState:
469       if (GET_CHIP_OS_VERSION() != OS_VERSION_4_0) {
470         ret = ESESTATUS_SUCCESS;
471       } else {
472         ret =
473             (ESESTATUS)ioctl((intptr_t)pDevHandle, P61_SET_DWNLD_STATUS, level);
474       }
475       break;
476 #if (NFC_NXP_ESE_VER == JCOP_VER_5_x)
477     case phPalEse_e_SetClientUpdateState: {
478       pNfcAdapt.Initialize();
479       ALOGD_IF(ese_debug_enabled,
480                "phPalEse_spi_ioctl state = phPalEse_e_SetJcopDwnldState");
481       ese_nxp_IoctlInOutData_t inpOutData;
482       memset(&inpOutData, 0x00, sizeof(ese_nxp_IoctlInOutData_t));
483       inpOutData.inp.data.nxpCmd.cmd_len = 1;
484       inpOutData.inp.data_source = 1;
485       uint8_t data = (uint8_t)level;
486       memcpy(inpOutData.inp.data.nxpCmd.p_cmd, &data, sizeof(data));
487       ALOGD_IF(ese_debug_enabled, "Before phPalEse_e_SetClientUpdateState");
488 
489       ret = pNfcAdapt.setEseUpdateState(&inpOutData);
490       ALOGD_IF(ese_debug_enabled, "After phPalEse_e_SetClientUpdateState");
491     } break;
492 #endif
493     case phPalEse_e_DisablePwrCntrl:
494       ret = ESESTATUS_SUCCESS;
495       break;
496     default:
497       ret = ESESTATUS_IOCTL_FAILED;
498       break;
499   }
500   ALOGD_IF(ese_debug_enabled, "Exit  phPalEse_spi_ioctl : ret = %d errno = %d",
501            ret, errno);
502   return (ESESTATUS)ret;
503 }
504