2 * Copyright (C) 2010 NXP Semiconductors
3 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * \file phDalNfc_i2c.c
20 * \brief DAL I2C port implementation for linux
22 * Project: Trusted NFC Linux
26 #define LOG_TAG "NFC_PLUGIN_NXP_I2C"
27 #include <cutils/log.h>
28 //#include <hardware/nfc.h>
33 #include <sys/ioctl.h>
34 #include <sys/select.h>
37 #include <phDal4Nfc_debug.h>
38 #include <phDal4Nfc_i2c.h>
39 #include <phOsalNfc.h>
40 #include <phNfcStatus.h>
45 //#include <linux/pn544.h>
54 } phDal4Nfc_I2cPortContext_t;
57 /*-----------------------------------------------------------------------------------
59 ------------------------------------------------------------------------------------*/
60 static phDal4Nfc_I2cPortContext_t gI2cPortContext;
64 /*-----------------------------------------------------------------------------
66 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
68 PURPOSE: Initialize internal variables
70 -----------------------------------------------------------------------------*/
72 void phDal4Nfc_i2c_initialize(void)
74 memset(&gI2cPortContext, 0, sizeof(phDal4Nfc_I2cPortContext_t));
78 /*-----------------------------------------------------------------------------
80 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
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
86 -----------------------------------------------------------------------------*/
88 void phDal4Nfc_i2c_set_open_from_handle(phHal_sHwReference_t * pDalHwContext)
90 gI2cPortContext.nHandle = (int) pDalHwContext->p_board_driver;
91 DAL_ASSERT_STR(gI2cPortContext.nHandle >= 0, "Bad passed com port handle");
92 gI2cPortContext.nOpened = 1;
95 /*-----------------------------------------------------------------------------
97 FUNCTION: phDal4Nfc_i2c_is_opened
99 PURPOSE: Returns if the link is opened or not. (0 = not opened; 1 = opened)
101 -----------------------------------------------------------------------------*/
103 int phDal4Nfc_i2c_is_opened(void)
105 return gI2cPortContext.nOpened;
108 /*-----------------------------------------------------------------------------
110 FUNCTION: phDal4Nfc_i2c_flush
112 PURPOSE: Flushes the link ; clears the link buffers
114 -----------------------------------------------------------------------------*/
116 void phDal4Nfc_i2c_flush(void)
118 /* Nothing to do (driver has no internal buffers) */
121 /*-----------------------------------------------------------------------------
123 FUNCTION: phDal4Nfc_i2c_close
125 PURPOSE: Closes the link
127 -----------------------------------------------------------------------------*/
129 void phDal4Nfc_i2c_close(void)
131 DAL_PRINT("Closing port\n");
132 if (gI2cPortContext.nOpened == 1)
134 close(gI2cPortContext.nHandle);
135 gI2cPortContext.nHandle = 0;
136 gI2cPortContext.nOpened = 0;
140 /*-----------------------------------------------------------------------------
142 FUNCTION: phDal4Nfc_i2c_open_and_configure
144 PURPOSE: Closes the link
146 -----------------------------------------------------------------------------*/
148 NFCSTATUS phDal4Nfc_i2c_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle)
150 DAL_ASSERT_STR(gI2cPortContext.nOpened==0, "Trying to open but already done!");
152 DAL_DEBUG("Opening port=%s\n", pConfig->deviceNode);
155 gI2cPortContext.nHandle = open(pConfig->deviceNode, O_RDWR | O_NOCTTY);
156 if (gI2cPortContext.nHandle < 0)
158 DAL_DEBUG("Open failed: open() returned %d\n", gI2cPortContext.nHandle);
160 return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
163 gI2cPortContext.nOpened = 1;
164 *pLinkHandle = (void*)gI2cPortContext.nHandle;
166 DAL_PRINT("Open succeed\n");
168 return NFCSTATUS_SUCCESS;
172 /*-----------------------------------------------------------------------------
174 FUNCTION: phDal4Nfc_i2c_read
176 PURPOSE: Reads nNbBytesToRead bytes and writes them in pBuffer.
177 Returns the number of bytes really read or -1 in case of error.
179 -----------------------------------------------------------------------------*/
181 int phDal4Nfc_i2c_read(uint8_t * pBuffer, int nNbBytesToRead)
188 DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "read called but not opened!");
189 DAL_DEBUG("_i2c_read() called to read %d bytes", nNbBytesToRead);
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) {
196 FD_SET(gI2cPortContext.nHandle, &rfds);
199 ret = select(gI2cPortContext.nHandle + 1, &rfds, NULL, NULL, &tv);
201 DAL_DEBUG("select() errno=%d", errno);
202 if (errno == EINTR || errno == EAGAIN) {
206 } else if (ret == 0) {
207 DAL_PRINT("timeout!");
210 ret = read(gI2cPortContext.nHandle, pBuffer + numRead, nNbBytesToRead - numRead);
212 DAL_DEBUG("read %d bytes", ret);
214 } else if (ret == 0) {
215 DAL_PRINT("_i2c_read() EOF");
218 DAL_DEBUG("_i2c_read() errno=%d", errno);
219 if (errno == EINTR || errno == EAGAIN) {
228 /*-----------------------------------------------------------------------------
230 FUNCTION: phDal4Nfc_i2c_write
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.
235 -----------------------------------------------------------------------------*/
237 int phDal4Nfc_i2c_write(uint8_t * pBuffer, int nNbBytesToWrite)
242 DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "write called but not opened!");
243 DAL_DEBUG("_i2c_write() called to write %d bytes\n", nNbBytesToWrite);
245 while (numWrote < nNbBytesToWrite) {
246 ret = write(gI2cPortContext.nHandle, pBuffer + numWrote, nNbBytesToWrite - numWrote);
248 DAL_DEBUG("wrote %d bytes", ret);
250 } else if (ret == 0) {
251 DAL_PRINT("_i2c_write() EOF");
254 DAL_DEBUG("_i2c_write() errno=%d", errno);
255 if (errno == EINTR || errno == EAGAIN) {
265 /*-----------------------------------------------------------------------------
267 FUNCTION: phDal4Nfc_i2c_reset
269 PURPOSE: Reset the PN544, using the VEN pin
271 -----------------------------------------------------------------------------*/
272 int phDal4Nfc_i2c_reset(long level)
274 DAL_DEBUG("phDal4Nfc_i2c_reset, VEN level = %ld", level);
276 return ioctl(gI2cPortContext.nHandle, PN544_SET_PWR, level);