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