• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *  Copyright 2020-2024 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 if (errno == ENOTCONN) {
194       NXPLOG_TML_E("%s [hdr] errno : %x", __func__, errno);
195       return -ENOTCONN;
196     } else {
197       NXPLOG_TML_E("%s [hdr] errno : %x", __func__, errno);
198       NXPLOG_TML_E(" %s pBuffer[0] = %x pBuffer[1]= %x", __func__, pBuffer[0],
199                    pBuffer[1]);
200       return -1;
201     }
202 
203     if (bFwDnldFlag && (pBuffer[0] != 0x00)) {
204       bFwDnldFlag = false;
205     }
206 
207     if (bFwDnldFlag == false) {
208       totalBtyesToRead = NORMAL_MODE_HEADER_LEN;
209     } else {
210       totalBtyesToRead = FW_DNLD_HEADER_LEN;
211     }
212 
213     if (numRead < totalBtyesToRead) {
214       ret_Read = read((int)(intptr_t)pDevHandle, (pBuffer + numRead),
215                       totalBtyesToRead - numRead);
216 
217       if (ret_Read != totalBtyesToRead - numRead) {
218         NXPLOG_TML_E("%s [hdr] errno : %x", __func__, errno);
219         return -1;
220       } else {
221         numRead += ret_Read;
222       }
223     }
224     if (bFwDnldFlag == true) {
225       totalBtyesToRead =
226           pBuffer[FW_DNLD_LEN_OFFSET] + FW_DNLD_HEADER_LEN + CRC_LEN;
227     } else {
228       totalBtyesToRead =
229           pBuffer[NORMAL_MODE_LEN_OFFSET] + NORMAL_MODE_HEADER_LEN;
230     }
231     if ((totalBtyesToRead - numRead) != 0) {
232       ret_Read = read((int)(intptr_t)pDevHandle, (pBuffer + numRead),
233                       totalBtyesToRead - numRead);
234       if (ret_Read > 0) {
235         numRead += ret_Read;
236       } else if (ret_Read == 0) {
237         NXPLOG_TML_E("%s [pyld] EOF", __func__);
238         return -1;
239       } else {
240         if (bFwDnldFlag == false) {
241           NXPLOG_TML_D("_i2c_read() [hdr] received");
242           phNxpNciHal_print_packet("RECV", pBuffer, NORMAL_MODE_HEADER_LEN);
243         }
244         NXPLOG_TML_E("%s [pyld] errno : %x", __func__, errno);
245         return -1;
246       }
247     } else {
248       NXPLOG_TML_E("%s _>>>>> Empty packet received !!", __func__);
249     }
250   }
251   return numRead;
252 }
253 
254 /*******************************************************************************
255 **
256 ** Function         Write
257 **
258 ** Description      Writes requested number of bytes from given buffer into
259 **                  NFCC device
260 **
261 ** Parameters       pDevHandle       - valid device handle
262 **                  pBuffer          - buffer for read data
263 **                  nNbBytesToWrite  - number of bytes requested to be written
264 **
265 ** Returns          numWrote   - number of successfully written bytes
266 **                  -1         - write operation failure
267 **
268 *******************************************************************************/
Write(void * pDevHandle,uint8_t * pBuffer,int nNbBytesToWrite)269 int NfccI2cTransport::Write(void* pDevHandle, uint8_t* pBuffer,
270                             int nNbBytesToWrite) {
271   int ret;
272   int numWrote = 0;
273   int numBytes = nNbBytesToWrite;
274   if (NULL == pDevHandle) {
275     return -1;
276   }
277   if (fragmentation_enabled == I2C_FRAGMENATATION_DISABLED &&
278       nNbBytesToWrite > gpphTmlNfc_Context->fragment_len) {
279     NXPLOG_TML_D(
280         "%s data larger than maximum I2C  size,enable I2C fragmentation",
281         __func__);
282     return -1;
283   }
284   while (numWrote < nNbBytesToWrite) {
285     if (fragmentation_enabled == I2C_FRAGMENTATION_ENABLED &&
286         nNbBytesToWrite > gpphTmlNfc_Context->fragment_len) {
287       if (nNbBytesToWrite - numWrote > gpphTmlNfc_Context->fragment_len) {
288         numBytes = numWrote + gpphTmlNfc_Context->fragment_len;
289       } else {
290         numBytes = nNbBytesToWrite;
291       }
292     }
293     ret = write((int)(intptr_t)pDevHandle, pBuffer + numWrote,
294                 numBytes - numWrote);
295     if (ret > 0) {
296       numWrote += ret;
297       if (fragmentation_enabled == I2C_FRAGMENTATION_ENABLED &&
298           numWrote < nNbBytesToWrite) {
299         usleep(500);
300       }
301     } else if (ret == 0) {
302       NXPLOG_TML_D("%s EOF", __func__);
303       return -1;
304     } else {
305       NXPLOG_TML_D("%s errno : %x", __func__, errno);
306       if (errno == EINTR || errno == EAGAIN) {
307         continue;
308       }
309       return -1;
310     }
311   }
312 
313   return numWrote;
314 }
315 
316 /*******************************************************************************
317 **
318 ** Function         Reset
319 **
320 ** Description      Reset NFCC device, using VEN pin
321 **
322 ** Parameters       pDevHandle     - valid device handle
323 **                  eType          - reset level
324 **
325 ** Returns           0   - reset operation success
326 **                  -1   - reset operation failure
327 **
328 *******************************************************************************/
NfccReset(void * pDevHandle,NfccResetType eType)329 int NfccI2cTransport::NfccReset(void* pDevHandle, NfccResetType eType) {
330   int ret = -1;
331   NXPLOG_TML_D("%s, VEN eType %u", __func__, eType);
332 
333   if (NULL == pDevHandle) {
334     return -1;
335   }
336 
337   ret = ioctl((int)(intptr_t)pDevHandle, NFC_SET_PWR, eType);
338   if (ret < 0) {
339     NXPLOG_TML_E("%s :failed errno = 0x%x", __func__, errno);
340   }
341   if ((eType != MODE_FW_DWNLD_WITH_VEN && eType != MODE_FW_DWND_HIGH) &&
342       ret == 0) {
343     bFwDnldFlag = false;
344   }
345 
346   return ret;
347 }
348 /*****************************************************************************
349  **
350  ** Function         UpdateReadPending
351  **
352  ** Description      Set/Reset Read Pending of NFC
353  **
354  ** Parameters       pDevHandle     - valid device handle
355  **                  eType          - set or clear the flag
356  **
357  ** Returns           0   - operation success
358  **                  -1   - operation failure
359  **
360  ****************************************************************************/
UpdateReadPending(void * pDevHandle,NfcReadPending eType)361 int NfccI2cTransport::UpdateReadPending(void* pDevHandle,
362                                         NfcReadPending eType) {
363   int ret = -1;
364   if (NULL == pDevHandle) {
365     return -1;
366   }
367   NXPLOG_TML_D("%s, %u", __func__, eType);
368   ret = ioctl((int)(intptr_t)pDevHandle, NFC_SET_RESET_READ_PENDING, eType);
369   if (ret != 0) {
370     NXPLOG_TML_E("%s: %u ret = 0x%x", __func__, eType, ret);
371   }
372   return ret;
373 }
374 
375 /*****************************************************************************
376  **
377  ** Function         NfcGetGpioStatus
378  **
379  ** Description      Get the gpio status flag byte from kernel space
380  **
381  ** Parameters       pDevHandle     - valid device handle
382  **
383  **
384  ** Returns           0   - operation success
385  **                  -1   - operation failure
386  **
387  ****************************************************************************/
NfcGetGpioStatus(void * pDevHandle,uint32_t * status)388 int NfccI2cTransport ::NfcGetGpioStatus(void* pDevHandle, uint32_t* status) {
389   int ret = -1;
390   if (NULL == pDevHandle) {
391     return ret;
392   }
393   ret = ioctl((int)(intptr_t)pDevHandle, NFC_GET_GPIO_STATUS, status);
394   if (ret != 0) {
395     NXPLOG_TML_E("%s: ret = 0x%x", __func__, ret);
396   }
397   NXPLOG_TML_D("%s, %d", __func__, *status);
398   return ret;
399 }
400 /*******************************************************************************
401 **
402 ** Function         EseReset
403 **
404 ** Description      Request NFCC to reset the eSE
405 **
406 ** Parameters       pDevHandle     - valid device handle
407 **                  eType          - EseResetType
408 **
409 ** Returns           0   - reset operation success
410 **                  else - reset operation failure
411 **
412 *******************************************************************************/
EseReset(void * pDevHandle,EseResetType eType)413 int NfccI2cTransport::EseReset(void* pDevHandle, EseResetType eType) {
414   int ret = -1;
415   NXPLOG_TML_D("%s, eType %u", __func__, eType);
416 
417   if (NULL == pDevHandle) {
418     return -1;
419   }
420   ret = ioctl((int)(intptr_t)pDevHandle, ESE_SET_PWR, eType);
421   if (ret < 0) {
422     NXPLOG_TML_E("%s :failed errno = 0x%x", __func__, errno);
423   }
424   return ret;
425 }
426 
427 /*******************************************************************************
428 **
429 ** Function         EnableFwDnldMode
430 **
431 ** Description      updates the state to Download mode
432 **
433 ** Parameters       True/False
434 **
435 ** Returns          None
436 *******************************************************************************/
EnableFwDnldMode(bool mode)437 void NfccI2cTransport::EnableFwDnldMode(bool mode) { bFwDnldFlag = mode; }
438 
439 /*******************************************************************************
440 **
441 ** Function         IsFwDnldModeEnabled
442 **
443 ** Description      Returns the current mode
444 **
445 ** Parameters       none
446 **
447 ** Returns           Current mode download/NCI
448 *******************************************************************************/
IsFwDnldModeEnabled(void)449 bool_t NfccI2cTransport::IsFwDnldModeEnabled(void) { return bFwDnldFlag; }
450