2 * Copyright (C) 2010 NXP Semiconductors
3 * Copyright (C) 2012 Samsung Elevtronics 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
27 //#include <utils/Log.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>
51 #define LOG_TAG "NFC_i2c"
58 } phDal4Nfc_I2cPortContext_t;
61 /*-----------------------------------------------------------------------------------
63 ------------------------------------------------------------------------------------*/
64 static phDal4Nfc_I2cPortContext_t gI2cPortContext;
68 /*-----------------------------------------------------------------------------
70 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
72 PURPOSE: Initialize internal variables
74 -----------------------------------------------------------------------------*/
76 void phDal4Nfc_i2c_initialize(void)
78 memset(&gI2cPortContext, 0, sizeof(phDal4Nfc_I2cPortContext_t));
82 /*-----------------------------------------------------------------------------
84 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
86 PURPOSE: The application could have opened the link itself. So we just need
87 to get the handle and consider that the open operation has already
90 -----------------------------------------------------------------------------*/
92 void phDal4Nfc_i2c_set_open_from_handle(phHal_sHwReference_t * pDalHwContext)
94 gI2cPortContext.nHandle = (int) pDalHwContext->p_board_driver;
95 DAL_ASSERT_STR(gI2cPortContext.nHandle >= 0, "Bad passed com port handle");
96 gI2cPortContext.nOpened = 1;
99 /*-----------------------------------------------------------------------------
101 FUNCTION: phDal4Nfc_i2c_is_opened
103 PURPOSE: Returns if the link is opened or not. (0 = not opened; 1 = opened)
105 -----------------------------------------------------------------------------*/
107 int phDal4Nfc_i2c_is_opened(void)
109 return gI2cPortContext.nOpened;
112 /*-----------------------------------------------------------------------------
114 FUNCTION: phDal4Nfc_i2c_flush
116 PURPOSE: Flushes the link ; clears the link buffers
118 -----------------------------------------------------------------------------*/
120 void phDal4Nfc_i2c_flush(void)
122 /* Nothing to do (driver has no internal buffers) */
125 /*-----------------------------------------------------------------------------
127 FUNCTION: phDal4Nfc_i2c_close
129 PURPOSE: Closes the link
131 -----------------------------------------------------------------------------*/
133 void phDal4Nfc_i2c_close(void)
135 DAL_PRINT("Closing port\n");
136 if (gI2cPortContext.nOpened == 1)
138 close(gI2cPortContext.nHandle);
139 gI2cPortContext.nHandle = 0;
140 gI2cPortContext.nOpened = 0;
144 /*-----------------------------------------------------------------------------
146 FUNCTION: phDal4Nfc_i2c_open_and_configure
148 PURPOSE: Closes the link
150 -----------------------------------------------------------------------------*/
152 NFCSTATUS phDal4Nfc_i2c_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle)
154 DAL_ASSERT_STR(gI2cPortContext.nOpened==0, "Trying to open but already done!");
156 DAL_DEBUG("Opening port=%s\n", pConfig->deviceNode);
\r
159 gI2cPortContext.nHandle = open(pConfig->deviceNode, O_RDWR | O_NOCTTY);
\r
160 if (gI2cPortContext.nHandle < 0)
162 DAL_DEBUG("Open failed: open() returned %d\n", gI2cPortContext.nHandle);
164 return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
167 gI2cPortContext.nOpened = 1;
168 *pLinkHandle = (void*)gI2cPortContext.nHandle;
170 DAL_PRINT("Open succeed\n");
172 return NFCSTATUS_SUCCESS;
176 /*-----------------------------------------------------------------------------
178 FUNCTION: phDal4Nfc_i2c_read
180 PURPOSE: Reads nNbBytesToRead bytes and writes them in pBuffer.
181 Returns the number of bytes really read or -1 in case of error.
183 -----------------------------------------------------------------------------*/
185 int phDal4Nfc_i2c_read(uint8_t * pBuffer, int nNbBytesToRead)
192 DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "read called but not opened!");
193 DAL_DEBUG("_i2c_read() called to read %d bytes", nNbBytesToRead);
195 // Read with 2 second timeout, so that the read thread can be aborted
196 // when the pn544 does not respond and we need to switch to FW download
197 // mode. This should be done via a control socket instead.
198 while (numRead < nNbBytesToRead) {
200 FD_SET(gI2cPortContext.nHandle, &rfds);
203 ret = select(gI2cPortContext.nHandle + 1, &rfds, NULL, NULL, &tv);
205 DAL_DEBUG("select() errno=%d", errno);
206 if (errno == EINTR || errno == EAGAIN) {
210 } else if (ret == 0) {
211 DAL_PRINT("timeout!");
214 ret = read(gI2cPortContext.nHandle, pBuffer + numRead, nNbBytesToRead - numRead);
216 DAL_DEBUG("read %d bytes", ret);
218 } else if (ret == 0) {
219 DAL_PRINT("_i2c_read() EOF");
222 DAL_DEBUG("_i2c_read() errno=%d", errno);
223 if (errno == EINTR || errno == EAGAIN) {
232 /*-----------------------------------------------------------------------------
234 FUNCTION: phDal4Nfc_i2c_write
236 PURPOSE: Writes nNbBytesToWrite bytes from pBuffer to the link
237 Returns the number of bytes that have been wrote to the interface or -1 in case of error.
239 -----------------------------------------------------------------------------*/
241 int phDal4Nfc_i2c_write(uint8_t * pBuffer, int nNbBytesToWrite)
246 DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "write called but not opened!");
247 DAL_DEBUG("_i2c_write() called to write %d bytes\n", nNbBytesToWrite);
249 while (numWrote < nNbBytesToWrite) {
250 ret = write(gI2cPortContext.nHandle, pBuffer + numWrote, nNbBytesToWrite - numWrote);
252 DAL_DEBUG("wrote %d bytes", ret);
254 } else if (ret == 0) {
255 DAL_PRINT("_i2c_write() EOF");
258 DAL_DEBUG("_i2c_write() errno=%d", errno);
259 if (errno == EINTR || errno == EAGAIN) {
269 /*-----------------------------------------------------------------------------
271 FUNCTION: phDal4Nfc_i2c_reset
273 PURPOSE: Reset the PN544, using the VEN pin
275 -----------------------------------------------------------------------------*/
276 int phDal4Nfc_i2c_reset(long level)
278 DAL_DEBUG("phDal4Nfc_i2c_reset, VEN level = %ld", level);
\r
280 return ioctl(gI2cPortContext.nHandle, PN544_SET_PWR, level);
\r