• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010-2014 NXP Semiconductors
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  * DAL I2C port implementation for linux
19  *
20  * Project: Trusted NFC Linux
21  *
22  */
23 #include <hardware/nfc.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <termios.h>
28 #include <sys/ioctl.h>
29 #include <sys/select.h>
30 #include <errno.h>
31 
32 #include <phNxpLog.h>
33 #include <phTmlNfc_i2c.h>
34 #include <phNfcStatus.h>
35 #include <string.h>
36 #include "phNxpNciHal_utils.h"
37 
38 #define CRC_LEN                     2
39 #define NORMAL_MODE_HEADER_LEN      3
40 #define FW_DNLD_HEADER_LEN          2
41 #define FW_DNLD_LEN_OFFSET          1
42 #define NORMAL_MODE_LEN_OFFSET      2
43 #define FRAGMENTSIZE_MAX            PHNFC_I2C_FRAGMENT_SIZE
44 static bool_t bFwDnldFlag = FALSE;
45 
46 /*******************************************************************************
47 **
48 ** Function         phTmlNfc_i2c_close
49 **
50 ** Description      Closes PN54X device
51 **
52 ** Parameters       pDevHandle - device handle
53 **
54 ** Returns          None
55 **
56 *******************************************************************************/
phTmlNfc_i2c_close(void * pDevHandle)57 void phTmlNfc_i2c_close(void *pDevHandle)
58 {
59     if (NULL != pDevHandle)
60     {
61         close((intptr_t)pDevHandle);
62     }
63 
64     return;
65 }
66 
67 /*******************************************************************************
68 **
69 ** Function         phTmlNfc_i2c_open_and_configure
70 **
71 ** Description      Open and configure PN54X device
72 **
73 ** Parameters       pConfig     - hardware information
74 **                  pLinkHandle - device handle
75 **
76 ** Returns          NFC status:
77 **                  NFCSTATUS_SUCCESS            - open_and_configure operation success
78 **                  NFCSTATUS_INVALID_DEVICE     - device open operation failure
79 **
80 *******************************************************************************/
phTmlNfc_i2c_open_and_configure(pphTmlNfc_Config_t pConfig,void ** pLinkHandle)81 NFCSTATUS phTmlNfc_i2c_open_and_configure(pphTmlNfc_Config_t pConfig, void ** pLinkHandle)
82 {
83     int nHandle;
84 
85 
86     NXPLOG_TML_D("Opening port=%s\n", pConfig->pDevName);
87     /* open port */
88     nHandle = open((char const *)pConfig->pDevName, O_RDWR);
89     if (nHandle < 0)
90     {
91         NXPLOG_TML_E("_i2c_open() Failed: retval %x",nHandle);
92         *pLinkHandle = NULL;
93         return NFCSTATUS_INVALID_DEVICE;
94     }
95 
96     *pLinkHandle = (void*) ((intptr_t)nHandle);
97 
98     /*Reset PN54X*/
99     phTmlNfc_i2c_reset((void *)((intptr_t)nHandle), 1);
100     usleep(100 * 1000);
101     phTmlNfc_i2c_reset((void *)((intptr_t)nHandle), 0);
102     usleep(100 * 1000);
103     phTmlNfc_i2c_reset((void *)((intptr_t)nHandle), 1);
104 
105     return NFCSTATUS_SUCCESS;
106 }
107 
108 /*******************************************************************************
109 **
110 ** Function         phTmlNfc_i2c_read
111 **
112 ** Description      Reads requested number of bytes from PN54X device into given buffer
113 **
114 ** Parameters       pDevHandle       - valid device handle
115 **                  pBuffer          - buffer for read data
116 **                  nNbBytesToRead   - number of bytes requested to be read
117 **
118 ** Returns          numRead   - number of successfully read bytes
119 **                  -1        - read operation failure
120 **
121 *******************************************************************************/
phTmlNfc_i2c_read(void * pDevHandle,uint8_t * pBuffer,int nNbBytesToRead)122 int phTmlNfc_i2c_read(void *pDevHandle, uint8_t * pBuffer, int nNbBytesToRead)
123 {
124     int ret_Read;
125     int ret_Select;
126     int numRead = 0;
127     struct timeval tv;
128     fd_set rfds;
129     uint16_t totalBtyesToRead = 0;
130 
131     int i;
132     UNUSED(nNbBytesToRead);
133     if (NULL == pDevHandle)
134     {
135         return -1;
136     }
137 
138     if (FALSE == bFwDnldFlag)
139     {
140         totalBtyesToRead = NORMAL_MODE_HEADER_LEN;
141     }
142     else
143     {
144         totalBtyesToRead = FW_DNLD_HEADER_LEN;
145     }
146 
147     /* Read with 2 second timeout, so that the read thread can be aborted
148        when the PN54X does not respond and we need to switch to FW download
149        mode. This should be done via a control socket instead. */
150     FD_ZERO(&rfds);
151     FD_SET((intptr_t) pDevHandle, &rfds);
152     tv.tv_sec = 2;
153     tv.tv_usec = 1;
154 
155     ret_Select = select((int)((intptr_t)pDevHandle + (int)1), &rfds, NULL, NULL, &tv);
156     if (ret_Select < 0)
157     {
158         NXPLOG_TML_E("i2c select() errno : %x",errno);
159         return -1;
160     }
161     else if (ret_Select == 0)
162     {
163         NXPLOG_TML_E("i2c select() Timeout");
164         return -1;
165     }
166     else
167     {
168         ret_Read = read((intptr_t)pDevHandle, pBuffer, totalBtyesToRead - numRead);
169         if (ret_Read > 0)
170         {
171             numRead += ret_Read;
172         }
173         else if (ret_Read == 0)
174         {
175             NXPLOG_TML_E("_i2c_read() [hdr]EOF");
176             return -1;
177         }
178         else
179         {
180             NXPLOG_TML_E("_i2c_read() [hdr] errno : %x",errno);
181             return -1;
182         }
183 
184         if (FALSE == bFwDnldFlag)
185         {
186             totalBtyesToRead = NORMAL_MODE_HEADER_LEN;
187         }
188         else
189         {
190             totalBtyesToRead = FW_DNLD_HEADER_LEN;
191         }
192 
193         if(numRead < totalBtyesToRead)
194         {
195             ret_Read = read((intptr_t)pDevHandle, pBuffer, totalBtyesToRead - numRead);
196             if (ret_Read != totalBtyesToRead - numRead)
197             {
198                 NXPLOG_TML_E("_i2c_read() [hdr] errno : %x",errno);
199                 return -1;
200             }
201             else
202             {
203                 numRead += ret_Read;
204             }
205         }
206         if(TRUE == bFwDnldFlag)
207         {
208             totalBtyesToRead = pBuffer[FW_DNLD_LEN_OFFSET] + FW_DNLD_HEADER_LEN + CRC_LEN;
209         }
210         else
211         {
212             totalBtyesToRead = pBuffer[NORMAL_MODE_LEN_OFFSET] + NORMAL_MODE_HEADER_LEN;
213         }
214         ret_Read = read((intptr_t)pDevHandle, (pBuffer + numRead), totalBtyesToRead - numRead);
215         if (ret_Read > 0)
216         {
217             numRead += ret_Read;
218         }
219         else if (ret_Read == 0)
220         {
221             NXPLOG_TML_E("_i2c_read() [pyld] EOF");
222             return -1;
223         }
224         else
225         {
226             if(FALSE == bFwDnldFlag)
227             {
228                 NXPLOG_TML_E("_i2c_read() [hdr] received");
229                 phNxpNciHal_print_packet("RECV",pBuffer, NORMAL_MODE_HEADER_LEN);
230             }
231             NXPLOG_TML_E("_i2c_read() [pyld] errno : %x",errno);
232             return -1;
233         }
234     }
235     return numRead;
236 }
237 
238 /*******************************************************************************
239 **
240 ** Function         phTmlNfc_i2c_write
241 **
242 ** Description      Writes requested number of bytes from given buffer into PN54X device
243 **
244 ** Parameters       pDevHandle       - valid device handle
245 **                  pBuffer          - buffer for read data
246 **                  nNbBytesToWrite  - number of bytes requested to be written
247 **
248 ** Returns          numWrote   - number of successfully written bytes
249 **                  -1         - write operation failure
250 **
251 *******************************************************************************/
phTmlNfc_i2c_write(void * pDevHandle,uint8_t * pBuffer,int nNbBytesToWrite)252 int phTmlNfc_i2c_write(void *pDevHandle, uint8_t * pBuffer, int nNbBytesToWrite)
253 {
254     int ret;
255     int numWrote = 0;
256     int i;
257     int numBytes = nNbBytesToWrite;
258     if (NULL == pDevHandle)
259     {
260         return -1;
261     }
262     if(fragmentation_enabled == I2C_FRAGMENATATION_DISABLED && nNbBytesToWrite > FRAGMENTSIZE_MAX)
263     {
264         NXPLOG_TML_E("i2c_write() data larger than maximum I2C  size,enable I2C fragmentation");
265         return -1;
266     }
267     while (numWrote < nNbBytesToWrite)
268     {
269         if(fragmentation_enabled == I2C_FRAGMENTATION_ENABLED && nNbBytesToWrite > FRAGMENTSIZE_MAX)
270         {
271             if(nNbBytesToWrite - numWrote > FRAGMENTSIZE_MAX)
272             {
273                 numBytes = numWrote+ FRAGMENTSIZE_MAX;
274             }
275             else
276             {
277                 numBytes = nNbBytesToWrite;
278             }
279         }
280         ret = write((intptr_t)pDevHandle, pBuffer + numWrote, numBytes - numWrote);
281         if (ret > 0)
282         {
283             numWrote += ret;
284             if(fragmentation_enabled == I2C_FRAGMENTATION_ENABLED && numWrote < nNbBytesToWrite)
285             {
286                 usleep(500);
287             }
288         }
289         else if (ret == 0)
290         {
291             NXPLOG_TML_E("_i2c_write() EOF");
292             return -1;
293         }
294         else
295         {
296             NXPLOG_TML_E("_i2c_write() errno : %x",errno);
297             if (errno == EINTR || errno == EAGAIN)
298             {
299                 continue;
300             }
301             return -1;
302         }
303     }
304 
305     return numWrote;
306 }
307 
308 /*******************************************************************************
309 **
310 ** Function         phTmlNfc_i2c_reset
311 **
312 ** Description      Reset PN54X device, using VEN pin
313 **
314 ** Parameters       pDevHandle     - valid device handle
315 **                  level          - reset level
316 **
317 ** Returns           0   - reset operation success
318 **                  -1   - reset operation failure
319 **
320 *******************************************************************************/
321 #define PN544_SET_PWR _IOW(0xe9, 0x01, unsigned int)
phTmlNfc_i2c_reset(void * pDevHandle,long level)322 int phTmlNfc_i2c_reset(void *pDevHandle, long level)
323 {
324     int ret;
325     NXPLOG_TML_D("phTmlNfc_i2c_reset(), VEN level %ld", level);
326 
327     if (NULL == pDevHandle)
328     {
329         return -1;
330     }
331 
332     ret = ioctl((intptr_t)pDevHandle, PN544_SET_PWR, level);
333     if(level == 2 && ret == 0)
334     {
335         bFwDnldFlag = TRUE;
336     }else{
337         bFwDnldFlag = FALSE;
338     }
339     return ret;
340 }
341 
342 /*******************************************************************************
343 **
344 ** Function         getDownloadFlag
345 **
346 ** Description      Returns the current mode
347 **
348 ** Parameters       none
349 **
350 ** Returns           Current mode download/NCI
351 *******************************************************************************/
getDownloadFlag(void)352 bool_t getDownloadFlag(void)
353 {
354 
355     return bFwDnldFlag;
356 }
357