• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *  Copyright 2020-2023 NXP
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *  http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  ******************************************************************************/
17 
18 /*
19  * DAL I2C port implementation for linux
20  *
21  * Project: Trusted NFC Linux
22  *
23  */
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <hardware/nfc.h>
27 #include <stdlib.h>
28 #include <sys/ioctl.h>
29 #include <sys/select.h>
30 #include <termios.h>
31 #include <unistd.h>
32 
33 #include <NfccI2cTransport.h>
34 #include <phNfcStatus.h>
35 #include <phNxpLog.h>
36 #include <string.h>
37 #include "phNxpNciHal_utils.h"
38 
39 #define CRC_LEN 2
40 #define NORMAL_MODE_HEADER_LEN 3
41 #define FW_DNLD_HEADER_LEN 2
42 #define FW_DNLD_LEN_OFFSET 1
43 #define NORMAL_MODE_LEN_OFFSET 2
44 #define FLUSH_BUFFER_SIZE 0xFF
45 extern phTmlNfc_i2cfragmentation_t fragmentation_enabled;
46 extern phTmlNfc_Context_t* gpphTmlNfc_Context;
47 /*******************************************************************************
48 **
49 ** Function         Close
50 **
51 ** Description      Closes NFCC device
52 **
53 ** Parameters       pDevHandle - device handle
54 **
55 ** Returns          None
56 **
57 *******************************************************************************/
Close(void * pDevHandle)58 void NfccI2cTransport::Close(void* pDevHandle) {
59   if (NULL != pDevHandle) {
60     close((int)(intptr_t)pDevHandle);
61   }
62   sem_destroy(&mTxRxSemaphore);
63   return;
64 }
65 
66 /*******************************************************************************
67 **
68 ** Function         OpenAndConfigure
69 **
70 ** Description      Open and configure NFCC device
71 **
72 ** Parameters       pConfig     - hardware information
73 **                  pLinkHandle - device handle
74 **
75 ** Returns          NFC status:
76 **                  NFCSTATUS_SUCCESS - open_and_configure operation success
77 **                  NFCSTATUS_INVALID_DEVICE - device open operation failure
78 **
79 *******************************************************************************/
OpenAndConfigure(pphTmlNfc_Config_t pConfig,void ** pLinkHandle)80 NFCSTATUS NfccI2cTransport::OpenAndConfigure(pphTmlNfc_Config_t pConfig,
81                                              void** pLinkHandle) {
82   int nHandle;
83   NFCSTATUS status = NFCSTATUS_SUCCESS;
84   NXPLOG_TML_D("%s Opening port=%s\n", __func__, pConfig->pDevName);
85   /* open port */
86   nHandle = open((const char*)pConfig->pDevName, O_RDWR);
87   if (nHandle < 0) {
88     NXPLOG_TML_E("_i2c_open() Failed: retval %x", nHandle);
89     *pLinkHandle = NULL;
90     status = NFCSTATUS_INVALID_DEVICE;
91   } else {
92     *pLinkHandle = (void*)((intptr_t)nHandle);
93     if (0 != sem_init(&mTxRxSemaphore, 0, 1)) {
94       NXPLOG_TML_E("%s Failed: reason sem_init : retval %x", __func__, nHandle);
95       status = NFCSTATUS_FAILED;
96     }
97   }
98   return status;
99 }
100 
101 /*******************************************************************************
102 **
103 ** Function         Flushdata
104 **
105 ** Description      Reads payload of FW rsp from NFCC device into given buffer
106 **
107 ** Parameters       pConfig     - hardware information
108 **
109 ** Returns          True(Success)/False(Fail)
110 **
111 *******************************************************************************/
Flushdata(pphTmlNfc_Config_t pConfig)112 bool NfccI2cTransport::Flushdata(pphTmlNfc_Config_t pConfig) {
113   int retRead = 0;
114   int nHandle;
115   uint8_t pBuffer[FLUSH_BUFFER_SIZE];
116   NXPLOG_TML_D("%s: Enter", __func__);
117   nHandle = open((const char*)pConfig->pDevName, O_RDWR | O_NONBLOCK);
118   if (nHandle < 0) {
119     NXPLOG_TML_E("%s: _i2c_open() Failed: retval %x", __func__, nHandle);
120     return false;
121   }
122   do {
123     retRead = read(nHandle, pBuffer, sizeof(pBuffer));
124     if (retRead > 0) {
125       phNxpNciHal_print_packet("RECV", pBuffer, retRead);
126       usleep(2 * 1000);
127     }
128   } while (retRead > 0);
129   close(nHandle);
130   NXPLOG_TML_D("%s: Exit", __func__);
131   return true;
132 }
133 
134 /*******************************************************************************
135 **
136 ** Function         Read
137 **
138 ** Description      Reads requested number of bytes from NFCC device into given
139 **                  buffer
140 **
141 ** Parameters       pDevHandle       - valid device handle
142 **                  pBuffer          - buffer for read data
143 **                  nNbBytesToRead   - number of bytes requested to be read
144 **
145 ** Returns          numRead   - number of successfully read bytes
146 **                  -1        - read operation failure
147 **
148 *******************************************************************************/
Read(void * pDevHandle,uint8_t * pBuffer,int nNbBytesToRead)149 int NfccI2cTransport::Read(void* pDevHandle, uint8_t* pBuffer,
150                            int nNbBytesToRead) {
151   int ret_Read;
152   int ret_Select;
153   int numRead = 0;
154   struct timeval tv;
155   fd_set rfds;
156   uint16_t totalBtyesToRead = 0;
157 
158   UNUSED_PROP(nNbBytesToRead);
159   if (NULL == pDevHandle) {
160     return -1;
161   }
162 
163   if (bFwDnldFlag == false) {
164     totalBtyesToRead = NORMAL_MODE_HEADER_LEN;
165   } else {
166     totalBtyesToRead = FW_DNLD_HEADER_LEN;
167   }
168 
169   /* Read with 2 second timeout, so that the read thread can be aborted
170      when the NFCC does not respond and we need to switch to FW download
171      mode. This should be done via a control socket instead. */
172   FD_ZERO(&rfds);
173   FD_SET((int)(intptr_t)pDevHandle, &rfds);
174   tv.tv_sec = 2;
175   tv.tv_usec = 1;
176 
177   ret_Select =
178       select((int)((intptr_t)pDevHandle + (int)1), &rfds, NULL, NULL, &tv);
179   if (ret_Select < 0) {
180     NXPLOG_TML_D("%s errno : %x", __func__, errno);
181     return -1;
182   } else if (ret_Select == 0) {
183     NXPLOG_TML_D("%s Timeout", __func__);
184     return -1;
185   } else {
186     ret_Read =
187         read((int)(intptr_t)pDevHandle, pBuffer, totalBtyesToRead - numRead);
188     if (ret_Read > 0 && !(pBuffer[0] == 0xFF && pBuffer[1] == 0xFF)) {
189       numRead += ret_Read;
190     } else if (ret_Read == 0) {
191       NXPLOG_TML_E("%s [hdr]EOF", __func__);
192       return -1;
193     } else {
194       NXPLOG_TML_E("%s [hdr] errno : %x", __func__, errno);
195       NXPLOG_TML_E(" %s pBuffer[0] = %x pBuffer[1]= %x", __func__, pBuffer[0],
196                    pBuffer[1]);
197       return -1;
198     }
199 
200     if (bFwDnldFlag && (pBuffer[0] != 0x00)) {
201       bFwDnldFlag = false;
202     }
203 
204     if (bFwDnldFlag == false) {
205       totalBtyesToRead = NORMAL_MODE_HEADER_LEN;
206     } else {
207       totalBtyesToRead = FW_DNLD_HEADER_LEN;
208     }
209 
210     if (numRead < totalBtyesToRead) {
211       ret_Read = read((int)(intptr_t)pDevHandle, (pBuffer + numRead),
212                       totalBtyesToRead - numRead);
213 
214       if (ret_Read != totalBtyesToRead - numRead) {
215         NXPLOG_TML_E("%s [hdr] errno : %x", __func__, errno);
216         return -1;
217       } else {
218         numRead += ret_Read;
219       }
220     }
221     if (bFwDnldFlag == true) {
222       totalBtyesToRead =
223           pBuffer[FW_DNLD_LEN_OFFSET] + FW_DNLD_HEADER_LEN + CRC_LEN;
224     } else {
225       totalBtyesToRead =
226           pBuffer[NORMAL_MODE_LEN_OFFSET] + NORMAL_MODE_HEADER_LEN;
227     }
228     if ((totalBtyesToRead - numRead) != 0) {
229       ret_Read = read((int)(intptr_t)pDevHandle, (pBuffer + numRead),
230                       totalBtyesToRead - numRead);
231       if (ret_Read > 0) {
232         numRead += ret_Read;
233       } else if (ret_Read == 0) {
234         NXPLOG_TML_E("%s [pyld] EOF", __func__);
235         return -1;
236       } else {
237         if (bFwDnldFlag == false) {
238           NXPLOG_TML_D("_i2c_read() [hdr] received");
239           phNxpNciHal_print_packet("RECV", pBuffer, NORMAL_MODE_HEADER_LEN);
240         }
241         NXPLOG_TML_E("%s [pyld] errno : %x", __func__, errno);
242         return -1;
243       }
244     } else {
245       NXPLOG_TML_E("%s _>>>>> Empty packet received !!", __func__);
246     }
247   }
248   return numRead;
249 }
250 
251 /*******************************************************************************
252 **
253 ** Function         Write
254 **
255 ** Description      Writes requested number of bytes from given buffer into
256 **                  NFCC device
257 **
258 ** Parameters       pDevHandle       - valid device handle
259 **                  pBuffer          - buffer for read data
260 **                  nNbBytesToWrite  - number of bytes requested to be written
261 **
262 ** Returns          numWrote   - number of successfully written bytes
263 **                  -1         - write operation failure
264 **
265 *******************************************************************************/
Write(void * pDevHandle,uint8_t * pBuffer,int nNbBytesToWrite)266 int NfccI2cTransport::Write(void* pDevHandle, uint8_t* pBuffer,
267                             int nNbBytesToWrite) {
268   int ret;
269   int numWrote = 0;
270   int numBytes = nNbBytesToWrite;
271   if (NULL == pDevHandle) {
272     return -1;
273   }
274   if (fragmentation_enabled == I2C_FRAGMENATATION_DISABLED &&
275       nNbBytesToWrite > gpphTmlNfc_Context->fragment_len) {
276     NXPLOG_TML_D(
277         "%s data larger than maximum I2C  size,enable I2C fragmentation",
278         __func__);
279     return -1;
280   }
281   while (numWrote < nNbBytesToWrite) {
282     if (fragmentation_enabled == I2C_FRAGMENTATION_ENABLED &&
283         nNbBytesToWrite > gpphTmlNfc_Context->fragment_len) {
284       if (nNbBytesToWrite - numWrote > gpphTmlNfc_Context->fragment_len) {
285         numBytes = numWrote + gpphTmlNfc_Context->fragment_len;
286       } else {
287         numBytes = nNbBytesToWrite;
288       }
289     }
290     ret = write((int)(intptr_t)pDevHandle, pBuffer + numWrote,
291                 numBytes - numWrote);
292     if (ret > 0) {
293       numWrote += ret;
294       if (fragmentation_enabled == I2C_FRAGMENTATION_ENABLED &&
295           numWrote < nNbBytesToWrite) {
296         usleep(500);
297       }
298     } else if (ret == 0) {
299       NXPLOG_TML_D("%s EOF", __func__);
300       return -1;
301     } else {
302       NXPLOG_TML_D("%s errno : %x", __func__, errno);
303       if (errno == EINTR || errno == EAGAIN) {
304         continue;
305       }
306       return -1;
307     }
308   }
309 
310   return numWrote;
311 }
312 
313 /*******************************************************************************
314 **
315 ** Function         Reset
316 **
317 ** Description      Reset NFCC device, using VEN pin
318 **
319 ** Parameters       pDevHandle     - valid device handle
320 **                  eType          - reset level
321 **
322 ** Returns           0   - reset operation success
323 **                  -1   - reset operation failure
324 **
325 *******************************************************************************/
NfccReset(void * pDevHandle,NfccResetType eType)326 int NfccI2cTransport::NfccReset(void* pDevHandle, NfccResetType eType) {
327   int ret = -1;
328   NXPLOG_TML_D("%s, VEN eType %u", __func__, eType);
329 
330   if (NULL == pDevHandle) {
331     return -1;
332   }
333 
334   ret = ioctl((int)(intptr_t)pDevHandle, NFC_SET_PWR, eType);
335   if (ret < 0) {
336     NXPLOG_TML_E("%s :failed errno = 0x%x", __func__, errno);
337   }
338   if ((eType != MODE_FW_DWNLD_WITH_VEN && eType != MODE_FW_DWND_HIGH) &&
339       ret == 0) {
340     bFwDnldFlag = false;
341   }
342 
343   return ret;
344 }
345 /*****************************************************************************
346  **
347  ** Function         UpdateReadPending
348  **
349  ** Description      Set/Reset Read Pending of NFC
350  **
351  ** Parameters       pDevHandle     - valid device handle
352  **                  eType          - set or clear the flag
353  **
354  ** Returns           0   - operation success
355  **                  -1   - operation failure
356  **
357  ****************************************************************************/
UpdateReadPending(void * pDevHandle,NfcReadPending eType)358 int NfccI2cTransport::UpdateReadPending(void* pDevHandle,
359                                         NfcReadPending eType) {
360   int ret = -1;
361   if (NULL == pDevHandle) {
362     return -1;
363   }
364   NXPLOG_TML_D("%s, %u", __func__, eType);
365   ret = ioctl((int)(intptr_t)pDevHandle, NFC_SET_RESET_READ_PENDING, eType);
366   if (ret != 0) {
367     NXPLOG_TML_E("%s: %u ret = 0x%x", __func__, eType, ret);
368   }
369   return ret;
370 }
371 
372 /*****************************************************************************
373  **
374  ** Function         NfcGetGpioStatus
375  **
376  ** Description      Get the gpio status flag byte from kernel space
377  **
378  ** Parameters       pDevHandle     - valid device handle
379  **
380  **
381  ** Returns           0   - operation success
382  **                  -1   - operation failure
383  **
384  ****************************************************************************/
NfcGetGpioStatus(void * pDevHandle,uint32_t * status)385 int NfccI2cTransport ::NfcGetGpioStatus(void* pDevHandle, uint32_t* status) {
386   int ret = -1;
387   if (NULL == pDevHandle) {
388     return ret;
389   }
390   ret = ioctl((int)(intptr_t)pDevHandle, NFC_GET_GPIO_STATUS, status);
391   if (ret != 0) {
392     NXPLOG_TML_E("%s: ret = 0x%x", __func__, ret);
393   }
394   NXPLOG_TML_D("%s, %d", __func__, *status);
395   return ret;
396 }
397 /*******************************************************************************
398 **
399 ** Function         EseReset
400 **
401 ** Description      Request NFCC to reset the eSE
402 **
403 ** Parameters       pDevHandle     - valid device handle
404 **                  eType          - EseResetType
405 **
406 ** Returns           0   - reset operation success
407 **                  else - reset operation failure
408 **
409 *******************************************************************************/
EseReset(void * pDevHandle,EseResetType eType)410 int NfccI2cTransport::EseReset(void* pDevHandle, EseResetType eType) {
411   int ret = -1;
412   NXPLOG_TML_D("%s, eType %u", __func__, eType);
413 
414   if (NULL == pDevHandle) {
415     return -1;
416   }
417   ret = ioctl((int)(intptr_t)pDevHandle, ESE_SET_PWR, eType);
418   if (ret < 0) {
419     NXPLOG_TML_E("%s :failed errno = 0x%x", __func__, errno);
420   }
421   return ret;
422 }
423 
424 /*******************************************************************************
425 **
426 ** Function         EnableFwDnldMode
427 **
428 ** Description      updates the state to Download mode
429 **
430 ** Parameters       True/False
431 **
432 ** Returns          None
433 *******************************************************************************/
EnableFwDnldMode(bool mode)434 void NfccI2cTransport::EnableFwDnldMode(bool mode) { bFwDnldFlag = mode; }
435 
436 /*******************************************************************************
437 **
438 ** Function         IsFwDnldModeEnabled
439 **
440 ** Description      Returns the current mode
441 **
442 ** Parameters       none
443 **
444 ** Returns           Current mode download/NCI
445 *******************************************************************************/
IsFwDnldModeEnabled(void)446 bool_t NfccI2cTransport::IsFwDnldModeEnabled(void) { return bFwDnldFlag; }
447