• 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_uart.c
19  * \brief DAL com port implementation for linux
20  *
21  * Project: Trusted NFC Linux Lignt
22  *
23  * $Date: 07 aug 2009
24  * $Author: Jonathan roux
25  * $Revision: 1.0 $
26  *
27  */
28 
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_uart.h>
37 #include <phOsalNfc.h>
38 #include <phNfcStatus.h>
39 #if defined(ANDROID)
40 #include <string.h>
41 #endif
42 
43 typedef struct
44 {
45    int  nHandle;
46    char nOpened;
47    struct termios nIoConfigBackup;
48    struct termios nIoConfig;
49 
50 } phDal4Nfc_ComPortContext_t;
51 
52 /*-----------------------------------------------------------------------------------
53                                 COM PORT CONFIGURATION
54 ------------------------------------------------------------------------------------*/
55 #define DAL_BAUD_RATE  B115200
56 
57 
58 
59 /*-----------------------------------------------------------------------------------
60                                       VARIABLES
61 ------------------------------------------------------------------------------------*/
62 static phDal4Nfc_ComPortContext_t gComPortContext;
63 
64 
65 
66 /*-----------------------------------------------------------------------------
67 
68 FUNCTION: phDal4Nfc_uart_set_open_from_handle
69 
70 PURPOSE:  Initialize internal variables
71 
72 -----------------------------------------------------------------------------*/
73 
phDal4Nfc_uart_initialize(void)74 void phDal4Nfc_uart_initialize(void)
75 {
76    memset(&gComPortContext, 0, sizeof(phDal4Nfc_ComPortContext_t));
77 }
78 
79 
80 /*-----------------------------------------------------------------------------
81 
82 FUNCTION: phDal4Nfc_uart_set_open_from_handle
83 
84 PURPOSE:  The application could have opened the link itself. So we just need
85           to get the handle and consider that the open operation has already
86           been done.
87 
88 -----------------------------------------------------------------------------*/
89 
phDal4Nfc_uart_set_open_from_handle(phHal_sHwReference_t * pDalHwContext)90 void phDal4Nfc_uart_set_open_from_handle(phHal_sHwReference_t * pDalHwContext)
91 {
92    gComPortContext.nHandle = (int) pDalHwContext->p_board_driver;
93    DAL_ASSERT_STR(gComPortContext.nHandle >= 0, "Bad passed com port handle");
94    gComPortContext.nOpened = 1;
95 }
96 
97 /*-----------------------------------------------------------------------------
98 
99 FUNCTION: phDal4Nfc_uart_is_opened
100 
101 PURPOSE:  Returns if the link is opened or not. (0 = not opened; 1 = opened)
102 
103 -----------------------------------------------------------------------------*/
104 
phDal4Nfc_uart_is_opened(void)105 int phDal4Nfc_uart_is_opened(void)
106 {
107    return gComPortContext.nOpened;
108 }
109 
110 /*-----------------------------------------------------------------------------
111 
112 FUNCTION: phDal4Nfc_uart_flush
113 
114 PURPOSE:  Flushes the link ; clears the link buffers
115 
116 -----------------------------------------------------------------------------*/
117 
phDal4Nfc_uart_flush(void)118 void phDal4Nfc_uart_flush(void)
119 {
120    int ret;
121    /* flushes the com port */
122    ret = tcflush(gComPortContext.nHandle, TCIFLUSH);
123    DAL_ASSERT_STR(ret!=-1, "tcflush failed");
124 }
125 
126 /*-----------------------------------------------------------------------------
127 
128 FUNCTION: phDal4Nfc_uart_close
129 
130 PURPOSE:  Closes the link
131 
132 -----------------------------------------------------------------------------*/
133 
phDal4Nfc_uart_close(void)134 void phDal4Nfc_uart_close(void)
135 {
136    if (gComPortContext.nOpened == 1)
137    {
138       close(gComPortContext.nHandle);
139       gComPortContext.nHandle = 0;
140       gComPortContext.nOpened = 0;
141    }
142 }
143 
144 /*-----------------------------------------------------------------------------
145 
146 FUNCTION: phDal4Nfc_uart_close
147 
148 PURPOSE:  Closes the link
149 
150 -----------------------------------------------------------------------------*/
151 
phDal4Nfc_uart_open_and_configure(pphDal4Nfc_sConfig_t pConfig,void ** pLinkHandle)152 NFCSTATUS phDal4Nfc_uart_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle)
153 {
154    char *       pComPort;
155    int          nComStatus;
156    NFCSTATUS    nfcret = NFCSTATUS_SUCCESS;
157    int          ret;
158 
159    DAL_ASSERT_STR(gComPortContext.nOpened==0, "Trying to open but already done!");
160 
161    switch(pConfig->nLinkType)
162    {
163      case ENUM_DAL_LINK_TYPE_COM1:
164       pComPort = "/dev/ttyS0";
165       break;
166      case ENUM_DAL_LINK_TYPE_COM2:
167       pComPort = "/dev/ttyS1";
168       break;
169      case ENUM_DAL_LINK_TYPE_COM3:
170       pComPort = "/dev/ttyS2";
171       break;
172      case ENUM_DAL_LINK_TYPE_COM4:
173       pComPort = "/dev/ttyS3";
174       break;
175      case ENUM_DAL_LINK_TYPE_COM5:
176       pComPort = "/dev/ttyS4";
177       break;
178      case ENUM_DAL_LINK_TYPE_COM6:
179       pComPort = "/dev/ttyS5";
180       break;
181      case ENUM_DAL_LINK_TYPE_COM7:
182       pComPort = "/dev/ttyS6";
183       break;
184      case ENUM_DAL_LINK_TYPE_COM8:
185       pComPort = "/dev/ttyS7";
186       break;
187      case ENUM_DAL_LINK_TYPE_USB:
188       pComPort = "/dev/ttyUSB0";
189       break;
190      default:
191       return NFCSTATUS_INVALID_PARAMETER;
192    }
193 
194    /* open communication port handle */
195    gComPortContext.nHandle = open(pComPort, O_RDWR | O_NOCTTY);
196    if (gComPortContext.nHandle < 0)
197    {
198       *pLinkHandle = NULL;
199       return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
200    }
201 
202    gComPortContext.nOpened = 1;
203    *pLinkHandle = (void*)gComPortContext.nHandle;
204 
205    /*
206     *  Now configure the com port
207     */
208    ret = tcgetattr(gComPortContext.nHandle, &gComPortContext.nIoConfigBackup); /* save the old io config */
209    if (ret == -1)
210    {
211       /* tcgetattr failed -- it is likely that the provided port is invalid */
212       *pLinkHandle = NULL;
213       return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
214    }
215    ret = fcntl(gComPortContext.nHandle, F_SETFL, 0); /* Makes the read blocking (default).  */
216    DAL_ASSERT_STR(ret != -1, "fcntl failed");
217    /* Configures the io */
218    memset((void *)&gComPortContext.nIoConfig, (int)0, (size_t)sizeof(struct termios));
219    /*
220     BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
221     CRTSCTS : output hardware flow control (only used if the cable has
222               all necessary lines. See sect. 7 of Serial-HOWTO)
223     CS8     : 8n1 (8bit,no parity,1 stopbit)
224     CLOCAL  : local connection, no modem contol
225     CREAD   : enable receiving characters
226    */
227    gComPortContext.nIoConfig.c_cflag = DAL_BAUD_RATE | CS8 | CLOCAL | CREAD;  /* Control mode flags */
228    gComPortContext.nIoConfig.c_iflag = IGNPAR;                                          /* Input   mode flags : IGNPAR  Ignore parity errors */
229    gComPortContext.nIoConfig.c_oflag = 0;                                               /* Output  mode flags */
230    gComPortContext.nIoConfig.c_lflag = 0;                                               /* Local   mode flags. Read mode : non canonical, no echo */
231    gComPortContext.nIoConfig.c_cc[VTIME] = 0;                                           /* Control characters. No inter-character timer */
232    gComPortContext.nIoConfig.c_cc[VMIN]  = 1;                                           /* Control characters. Read is blocking until X characters are read */
233 
234    /*
235       TCSANOW  Make changes now without waiting for data to complete
236       TCSADRAIN   Wait until everything has been transmitted
237       TCSAFLUSH   Flush input and output buffers and make the change
238    */
239    ret = tcsetattr(gComPortContext.nHandle, TCSANOW, &gComPortContext.nIoConfig);
240    DAL_ASSERT_STR(ret != -1, "tcsetattr failed");
241 
242    /*
243       On linux the DTR signal is set by default. That causes a problem for pn544 chip
244       because this signal is connected to "reset". So we clear it. (on windows it is cleared by default).
245    */
246    ret = ioctl(gComPortContext.nHandle, TIOCMGET, &nComStatus);
247    DAL_ASSERT_STR(ret != -1, "ioctl TIOCMGET failed");
248    nComStatus &= ~TIOCM_DTR;
249    ret = ioctl(gComPortContext.nHandle, TIOCMSET, &nComStatus);
250    DAL_ASSERT_STR(ret != -1, "ioctl TIOCMSET failed");
251    DAL_DEBUG("Com port status=%d\n", nComStatus);
252    usleep(10000); /* Mandatory sleep so that the DTR line is ready before continuing */
253 
254    return nfcret;
255 }
256 
257 
258 /*-----------------------------------------------------------------------------
259 
260 FUNCTION: phDal4Nfc_uart_read
261 
262 PURPOSE:  Reads nNbBytesToRead bytes and writes them in pBuffer.
263           Returns the number of bytes really read or -1 in case of error.
264 
265 -----------------------------------------------------------------------------*/
266 
phDal4Nfc_uart_read(uint8_t * pBuffer,int nNbBytesToRead)267 int phDal4Nfc_uart_read(uint8_t * pBuffer, int nNbBytesToRead)
268 {
269    fd_set rfds;
270    struct timeval tv;
271    int ret;
272 
273    DAL_ASSERT_STR(gComPortContext.nOpened == 1, "read called but not opened!");
274 
275    FD_ZERO(&rfds);
276    FD_SET(gComPortContext.nHandle, &rfds);
277 
278    /* select will block for 10 sec */
279    tv.tv_sec = 2;
280    tv.tv_usec = 0;
281 
282    ret = select(gComPortContext.nHandle + 1, &rfds, NULL, NULL, &tv);
283 
284    if (ret == -1)
285       return -1;
286 
287    if (ret)
288       return read(gComPortContext.nHandle, pBuffer, nNbBytesToRead);
289 
290    return 0;
291 }
292 
293 /*-----------------------------------------------------------------------------
294 
295 FUNCTION: phDal4Nfc_link_write
296 
297 PURPOSE:  Writes nNbBytesToWrite bytes from pBuffer to the link
298           Returns the number of bytes that have been wrote to the interface or -1 in case of error.
299 
300 -----------------------------------------------------------------------------*/
301 
phDal4Nfc_uart_write(uint8_t * pBuffer,int nNbBytesToWrite)302 int phDal4Nfc_uart_write(uint8_t * pBuffer, int nNbBytesToWrite)
303 {
304    fd_set wfds;
305    struct timeval tv;
306    int ret;
307 
308    DAL_ASSERT_STR(gComPortContext.nOpened == 1, "write called but not opened!");
309 
310    FD_ZERO(&wfds);
311    FD_SET(gComPortContext.nHandle, &wfds);
312 
313    /* select will block for 10 sec */
314    tv.tv_sec = 2;
315    tv.tv_usec = 0;
316 
317    ret = select(gComPortContext.nHandle + 1, NULL, &wfds, NULL, &tv);
318 
319    if (ret == -1)
320       return -1;
321 
322    if (ret)
323       return write(gComPortContext.nHandle, pBuffer, nNbBytesToWrite);
324 
325    return 0;
326 }
327 
328 /*-----------------------------------------------------------------------------
329 
330 FUNCTION: phDal4Nfc_uart_reset
331 
332 PURPOSE:  Reset the PN544, using the VEN pin
333 
334 -----------------------------------------------------------------------------*/
phDal4Nfc_uart_reset()335 int phDal4Nfc_uart_reset()
336 {
337    DAL_PRINT("phDal4Nfc_uart_reset");
338 
339    return NFCSTATUS_FEATURE_NOT_SUPPORTED;
340 }
341 
342 /*-----------------------------------------------------------------------------
343 
344 FUNCTION: phDal4Nfc_uart_write
345 
346 PURPOSE:  Put the PN544 in download mode, using the GPIO4 pin
347 
348 -----------------------------------------------------------------------------*/
phDal4Nfc_uart_download()349 int phDal4Nfc_uart_download()
350 {
351    DAL_PRINT("phDal4Nfc_uart_download");
352 
353    return NFCSTATUS_FEATURE_NOT_SUPPORTED;
354 }
355 
356