1 /******************************************************************************
2 * Copyright 2020-2021 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 **
348 ** Function EseReset
349 **
350 ** Description Request NFCC to reset the eSE
351 **
352 ** Parameters pDevHandle - valid device handle
353 ** eType - EseResetType
354 **
355 ** Returns 0 - reset operation success
356 ** else - reset operation failure
357 **
358 *******************************************************************************/
EseReset(void * pDevHandle,EseResetType eType)359 int NfccI2cTransport::EseReset(void* pDevHandle, EseResetType eType) {
360 int ret = -1;
361 NXPLOG_TML_D("%s, eType %u", __func__, eType);
362
363 if (NULL == pDevHandle) {
364 return -1;
365 }
366 ret = ioctl((int)(intptr_t)pDevHandle, ESE_SET_PWR, eType);
367 if (ret < 0) {
368 NXPLOG_TML_E("%s :failed errno = 0x%x", __func__, errno);
369 }
370 return ret;
371 }
372
373 /*******************************************************************************
374 **
375 ** Function EseGetPower
376 **
377 ** Description Request NFCC to reset the eSE
378 **
379 ** Parameters pDevHandle - valid device handle
380 ** level - reset level
381 **
382 ** Returns 0 - reset operation success
383 ** else - reset operation failure
384 **
385 *******************************************************************************/
EseGetPower(void * pDevHandle,uint32_t level)386 int NfccI2cTransport::EseGetPower(void* pDevHandle, uint32_t level) {
387 return ioctl((int)(intptr_t)pDevHandle, ESE_GET_PWR, level);
388 }
389
390 /*******************************************************************************
391 **
392 ** Function EnableFwDnldMode
393 **
394 ** Description updates the state to Download mode
395 **
396 ** Parameters True/False
397 **
398 ** Returns None
399 *******************************************************************************/
EnableFwDnldMode(bool mode)400 void NfccI2cTransport::EnableFwDnldMode(bool mode) { bFwDnldFlag = mode; }
401
402 /*******************************************************************************
403 **
404 ** Function IsFwDnldModeEnabled
405 **
406 ** Description Returns the current mode
407 **
408 ** Parameters none
409 **
410 ** Returns Current mode download/NCI
411 *******************************************************************************/
IsFwDnldModeEnabled(void)412 bool_t NfccI2cTransport::IsFwDnldModeEnabled(void) { return bFwDnldFlag; }
413