• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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  * \file phDalNfc_i2c.c
19  * \brief DAL I2C port implementation for linux
20  *
21  * Project: Trusted NFC Linux
22  *
23  */
24 
25 #define LOG_TAG "NFC_i2c"
26 #include <utils/Log.h>
27 
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <termios.h>
32 #include <sys/ioctl.h>
33 #include <sys/select.h>
34 
35 #include <phDal4Nfc_debug.h>
36 #include <phDal4Nfc_i2c.h>
37 #include <phOsalNfc.h>
38 #include <phNfcStatus.h>
39 #if defined(ANDROID)
40 #include <string.h>
41 #endif
42 
43 #include <linux/pn544.h>
44 
45 typedef struct
46 {
47    int  nHandle;
48    char nOpened;
49 
50 } phDal4Nfc_I2cPortContext_t;
51 
52 
53 /*-----------------------------------------------------------------------------------
54                                       VARIABLES
55 ------------------------------------------------------------------------------------*/
56 static phDal4Nfc_I2cPortContext_t gI2cPortContext;
57 
58 
59 
60 /*-----------------------------------------------------------------------------
61 
62 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
63 
64 PURPOSE:  Initialize internal variables
65 
66 -----------------------------------------------------------------------------*/
67 
phDal4Nfc_i2c_initialize(void)68 void phDal4Nfc_i2c_initialize(void)
69 {
70    memset(&gI2cPortContext, 0, sizeof(phDal4Nfc_I2cPortContext_t));
71 }
72 
73 
74 /*-----------------------------------------------------------------------------
75 
76 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
77 
78 PURPOSE:  The application could have opened the link itself. So we just need
79           to get the handle and consider that the open operation has already
80           been done.
81 
82 -----------------------------------------------------------------------------*/
83 
phDal4Nfc_i2c_set_open_from_handle(phHal_sHwReference_t * pDalHwContext)84 void phDal4Nfc_i2c_set_open_from_handle(phHal_sHwReference_t * pDalHwContext)
85 {
86    gI2cPortContext.nHandle = (int) pDalHwContext->p_board_driver;
87    DAL_ASSERT_STR(gI2cPortContext.nHandle >= 0, "Bad passed com port handle");
88    gI2cPortContext.nOpened = 1;
89 }
90 
91 /*-----------------------------------------------------------------------------
92 
93 FUNCTION: phDal4Nfc_i2c_is_opened
94 
95 PURPOSE:  Returns if the link is opened or not. (0 = not opened; 1 = opened)
96 
97 -----------------------------------------------------------------------------*/
98 
phDal4Nfc_i2c_is_opened(void)99 int phDal4Nfc_i2c_is_opened(void)
100 {
101    return gI2cPortContext.nOpened;
102 }
103 
104 /*-----------------------------------------------------------------------------
105 
106 FUNCTION: phDal4Nfc_i2c_flush
107 
108 PURPOSE:  Flushes the link ; clears the link buffers
109 
110 -----------------------------------------------------------------------------*/
111 
phDal4Nfc_i2c_flush(void)112 void phDal4Nfc_i2c_flush(void)
113 {
114    /* Nothing to do (driver has no internal buffers) */
115 }
116 
117 /*-----------------------------------------------------------------------------
118 
119 FUNCTION: phDal4Nfc_i2c_close
120 
121 PURPOSE:  Closes the link
122 
123 -----------------------------------------------------------------------------*/
124 
phDal4Nfc_i2c_close(void)125 void phDal4Nfc_i2c_close(void)
126 {
127    DAL_PRINT("Closing port\n");
128    if (gI2cPortContext.nOpened == 1)
129    {
130       close(gI2cPortContext.nHandle);
131       gI2cPortContext.nHandle = 0;
132       gI2cPortContext.nOpened = 0;
133    }
134 }
135 
136 /*-----------------------------------------------------------------------------
137 
138 FUNCTION: phDal4Nfc_i2c_open_and_configure
139 
140 PURPOSE:  Closes the link
141 
142 -----------------------------------------------------------------------------*/
143 
phDal4Nfc_i2c_open_and_configure(pphDal4Nfc_sConfig_t pConfig,void ** pLinkHandle)144 NFCSTATUS phDal4Nfc_i2c_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle)
145 {
146    char *       pComPort;
147 
148    DAL_ASSERT_STR(gI2cPortContext.nOpened==0, "Trying to open but already done!");
149 
150    switch(pConfig->nLinkType)
151    {
152        case ENUM_DAL_LINK_TYPE_I2C:
153           pComPort = "/dev/pn544";
154           break;
155        default:
156           DAL_DEBUG("Open failed: unknown type %d\n", pConfig->nLinkType);
157           return NFCSTATUS_INVALID_PARAMETER;
158    }
159 
160    DAL_DEBUG("Opening port=%s\n", pComPort);
161 
162    /* open port */
163    gI2cPortContext.nHandle = open(pComPort, O_RDWR | O_NOCTTY);
164    if (gI2cPortContext.nHandle < 0)
165    {
166        DAL_DEBUG("Open failed: open() returned %d\n", gI2cPortContext.nHandle);
167       *pLinkHandle = NULL;
168       return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
169    }
170 
171    gI2cPortContext.nOpened = 1;
172    *pLinkHandle = (void*)gI2cPortContext.nHandle;
173 
174    DAL_PRINT("Open succeed\n");
175 
176    return NFCSTATUS_SUCCESS;
177 }
178 
179 
180 /*-----------------------------------------------------------------------------
181 
182 FUNCTION: phDal4Nfc_i2c_read
183 
184 PURPOSE:  Reads nNbBytesToRead bytes and writes them in pBuffer.
185           Returns the number of bytes really read or -1 in case of error.
186 
187 -----------------------------------------------------------------------------*/
188 
phDal4Nfc_i2c_read(uint8_t * pBuffer,int nNbBytesToRead)189 int phDal4Nfc_i2c_read(uint8_t * pBuffer, int nNbBytesToRead)
190 {
191    int ret;
192    DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "read called but not opened!");
193 
194    DAL_DEBUG("Reading %d bytes\n", nNbBytesToRead);
195    ret = read(gI2cPortContext.nHandle, pBuffer, nNbBytesToRead);
196    if (ret < 0)
197    {
198       DAL_DEBUG("Read failed: read() returned %d\n", ret);
199    }
200    else
201    {
202       DAL_DEBUG("Read succeed (%d bytes)\n", ret);
203    }
204    return ret;
205 }
206 
207 /*-----------------------------------------------------------------------------
208 
209 FUNCTION: phDal4Nfc_i2c_write
210 
211 PURPOSE:  Writes nNbBytesToWrite bytes from pBuffer to the link
212           Returns the number of bytes that have been wrote to the interface or -1 in case of error.
213 
214 -----------------------------------------------------------------------------*/
215 
phDal4Nfc_i2c_write(uint8_t * pBuffer,int nNbBytesToWrite)216 int phDal4Nfc_i2c_write(uint8_t * pBuffer, int nNbBytesToWrite)
217 {
218    int ret;
219    DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "write called but not opened!");
220 
221    DAL_DEBUG("Writing %d bytes\n", nNbBytesToWrite);
222    ret = write(gI2cPortContext.nHandle, pBuffer, nNbBytesToWrite);
223    if (ret < 0)
224    {
225       DAL_DEBUG("Write failed: write() returned %d \n", ret);
226    }
227    else
228    {
229       DAL_DEBUG("Write succeed (%d bytes)\n", ret);
230    }
231    return ret;
232 }
233 
234 
235 /*-----------------------------------------------------------------------------
236 
237 FUNCTION: phDal4Nfc_i2c_reset
238 
239 PURPOSE:  Reset the PN544, using the VEN pin
240 
241 -----------------------------------------------------------------------------*/
phDal4Nfc_i2c_reset(long level)242 int phDal4Nfc_i2c_reset(long level)
243 {
244    int ret = NFCSTATUS_SUCCESS;
245 
246    DAL_DEBUG("phDal4Nfc_i2c_reset, VEN level = %ld",level);
247 
248    ret = ioctl(gI2cPortContext.nHandle, PN544_SET_PWR, level);
249 
250    /* HACK to increase reset time
251     * TODO: move this to kernel
252     */
253    if (level == 0) {
254        LOGW("sleeping a little longer...");
255        usleep(50000);
256    } else {
257        usleep(10000);
258    }
259 
260    return ret;
261 }
262 
263 
264 
265 
266 
267