code update
[adaptation/devices/nfc-plugin-nxp.git] / Linux_x86 / phDal4Nfc_i2c.c
1 /*
2  * Copyright (C) 2010 NXP Semiconductors
3  * Copyright (C) 2012 Samsung Elevtronics Co., Ltd
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /**
19  * \file phDalNfc_i2c.c
20  * \brief DAL I2C port implementation for linux
21  *
22  * Project: Trusted NFC Linux
23  *
24  */
25
26 #define LOG_TAG "NFC_i2c"\r
27 #include <cutils/log.h>\r
28 //#include <hardware/nfc.h>\r
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <termios.h>
33 #include <sys/ioctl.h>
34 #include <sys/select.h>
35 #include <errno.h>
36
37 #include <phDal4Nfc_debug.h>
38 #include <phDal4Nfc_i2c.h>
39 #include <phOsalNfc.h>
40 #include <phNfcStatus.h>
41 #if defined(ANDROID)
42 #include <string.h>
43 #endif
44
45 //#include <linux/pn544.h>
46 #include "pn544.h"
47
48
49 typedef struct
50 {
51    int  nHandle;
52    char nOpened;
53
54 } phDal4Nfc_I2cPortContext_t;
55
56
57 /*-----------------------------------------------------------------------------------
58                                       VARIABLES
59 ------------------------------------------------------------------------------------*/
60 static phDal4Nfc_I2cPortContext_t gI2cPortContext;
61
62
63
64 /*-----------------------------------------------------------------------------
65
66 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
67
68 PURPOSE:  Initialize internal variables
69
70 -----------------------------------------------------------------------------*/
71
72 void phDal4Nfc_i2c_initialize(void)
73 {
74    memset(&gI2cPortContext, 0, sizeof(phDal4Nfc_I2cPortContext_t));
75 }
76
77
78 /*-----------------------------------------------------------------------------
79
80 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
81
82 PURPOSE:  The application could have opened the link itself. So we just need
83           to get the handle and consider that the open operation has already
84           been done.
85
86 -----------------------------------------------------------------------------*/
87
88 void phDal4Nfc_i2c_set_open_from_handle(phHal_sHwReference_t * pDalHwContext)
89 {
90    gI2cPortContext.nHandle = (int) pDalHwContext->p_board_driver;
91    DAL_ASSERT_STR(gI2cPortContext.nHandle >= 0, "Bad passed com port handle");
92    gI2cPortContext.nOpened = 1;
93 }
94
95 /*-----------------------------------------------------------------------------
96
97 FUNCTION: phDal4Nfc_i2c_is_opened
98
99 PURPOSE:  Returns if the link is opened or not. (0 = not opened; 1 = opened)
100
101 -----------------------------------------------------------------------------*/
102
103 int phDal4Nfc_i2c_is_opened(void)
104 {
105    return gI2cPortContext.nOpened;
106 }
107
108 /*-----------------------------------------------------------------------------
109
110 FUNCTION: phDal4Nfc_i2c_flush
111
112 PURPOSE:  Flushes the link ; clears the link buffers
113
114 -----------------------------------------------------------------------------*/
115
116 void phDal4Nfc_i2c_flush(void)
117 {
118    /* Nothing to do (driver has no internal buffers) */
119 }
120
121 /*-----------------------------------------------------------------------------
122
123 FUNCTION: phDal4Nfc_i2c_close
124
125 PURPOSE:  Closes the link
126
127 -----------------------------------------------------------------------------*/
128
129 void phDal4Nfc_i2c_close(void)
130 {
131    DAL_PRINT("Closing port\n");
132    if (gI2cPortContext.nOpened == 1)
133    {
134       close(gI2cPortContext.nHandle);
135       gI2cPortContext.nHandle = 0;
136       gI2cPortContext.nOpened = 0;
137    }
138 }
139
140 /*-----------------------------------------------------------------------------
141
142 FUNCTION: phDal4Nfc_i2c_open_and_configure
143
144 PURPOSE:  Closes the link
145
146 -----------------------------------------------------------------------------*/
147
148 NFCSTATUS phDal4Nfc_i2c_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle)
149 {
150    DAL_ASSERT_STR(gI2cPortContext.nOpened==0, "Trying to open but already done!");
151
152    DAL_DEBUG("Opening port=%s\n", pConfig->deviceNode);\r
153
154    /* open port */
155    gI2cPortContext.nHandle = open(pConfig->deviceNode, O_RDWR | O_NOCTTY);\r
156    if (gI2cPortContext.nHandle < 0)
157    {
158        DAL_DEBUG("Open failed: open() returned %d\n", gI2cPortContext.nHandle);
159       *pLinkHandle = NULL;
160       return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
161    }
162
163    gI2cPortContext.nOpened = 1;
164    *pLinkHandle = (void*)gI2cPortContext.nHandle;
165
166    DAL_PRINT("Open succeed\n");
167
168    return NFCSTATUS_SUCCESS;
169 }
170
171
172 /*-----------------------------------------------------------------------------
173
174 FUNCTION: phDal4Nfc_i2c_read
175
176 PURPOSE:  Reads nNbBytesToRead bytes and writes them in pBuffer.
177           Returns the number of bytes really read or -1 in case of error.
178
179 -----------------------------------------------------------------------------*/
180
181 int phDal4Nfc_i2c_read(uint8_t * pBuffer, int nNbBytesToRead)
182 {
183     int ret;
184     int numRead = 0;
185     struct timeval tv;
186     fd_set rfds;
187
188     DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "read called but not opened!");
189     DAL_DEBUG("_i2c_read() called to read %d bytes", nNbBytesToRead);
190
191     // Read with 2 second timeout, so that the read thread can be aborted
192     // when the pn544 does not respond and we need to switch to FW download
193     // mode. This should be done via a control socket instead.
194     while (numRead < nNbBytesToRead) {
195         FD_ZERO(&rfds);
196         FD_SET(gI2cPortContext.nHandle, &rfds);
197         tv.tv_sec = 2;
198         tv.tv_usec = 0;
199         ret = select(gI2cPortContext.nHandle + 1, &rfds, NULL, NULL, &tv);
200         if (ret < 0) {
201             DAL_DEBUG("select() errno=%d", errno);
202             if (errno == EINTR || errno == EAGAIN) {
203                 continue;
204             }
205             return -1;
206         } else if (ret == 0) {
207             DAL_PRINT("timeout!");
208             return -1;
209         }
210         ret = read(gI2cPortContext.nHandle, pBuffer + numRead, nNbBytesToRead - numRead);
211         if (ret > 0) {
212             DAL_DEBUG("read %d bytes", ret);
213             numRead += ret;
214         } else if (ret == 0) {
215             DAL_PRINT("_i2c_read() EOF");
216             return -1;
217         } else {
218             DAL_DEBUG("_i2c_read() errno=%d", errno);
219             if (errno == EINTR || errno == EAGAIN) {
220                 continue;
221             }
222             return -1;
223         }
224     }
225     return numRead;
226 }
227
228 /*-----------------------------------------------------------------------------
229
230 FUNCTION: phDal4Nfc_i2c_write
231
232 PURPOSE:  Writes nNbBytesToWrite bytes from pBuffer to the link
233           Returns the number of bytes that have been wrote to the interface or -1 in case of error.
234
235 -----------------------------------------------------------------------------*/
236
237 int phDal4Nfc_i2c_write(uint8_t * pBuffer, int nNbBytesToWrite)
238 {
239     int ret;
240     int numWrote = 0;
241
242     DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "write called but not opened!");
243     DAL_DEBUG("_i2c_write() called to write %d bytes\n", nNbBytesToWrite);
244
245     while (numWrote < nNbBytesToWrite) {
246         ret = write(gI2cPortContext.nHandle, pBuffer + numWrote, nNbBytesToWrite - numWrote);
247         if (ret > 0) {
248             DAL_DEBUG("wrote %d bytes", ret);
249             numWrote += ret;
250         } else if (ret == 0) {
251             DAL_PRINT("_i2c_write() EOF");
252             return -1;
253         } else {
254             DAL_DEBUG("_i2c_write() errno=%d", errno);
255             if (errno == EINTR || errno == EAGAIN) {
256                 continue;
257             }
258             return -1;
259         }
260     }
261
262     return numWrote;
263 }
264
265 /*-----------------------------------------------------------------------------
266
267 FUNCTION: phDal4Nfc_i2c_reset
268
269 PURPOSE:  Reset the PN544, using the VEN pin
270
271 -----------------------------------------------------------------------------*/
272 int phDal4Nfc_i2c_reset(long level)
273 {
274     DAL_DEBUG("phDal4Nfc_i2c_reset, VEN level = %ld", level);\r
275
276     return ioctl(gI2cPortContext.nHandle, PN544_SET_PWR, level);\r
277 }
278
279