1 /*-
2 * Free/Libre Near Field Communication (NFC) library
3 *
4 * Libnfc historical contributors:
5 * Copyright (C) 2009 Roel Verdult
6 * Copyright (C) 2009-2013 Romuald Conty
7 * Copyright (C) 2010-2012 Romain Tartière
8 * Copyright (C) 2010-2013 Philippe Teuwen
9 * Copyright (C) 2012-2013 Ludovic Rousseau
10 * See AUTHORS file for a more comprehensive list of contributors.
11 * Additional contributors of this file:
12 *
13 * This program is free software: you can redistribute it and/or modify it
14 * under the terms of the GNU Lesser General Public License as published by the
15 * Free Software Foundation, either version 3 of the License, or (at your
16 * option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful, but WITHOUT
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>
25 *
26 */
27
28 /**
29 * @file uart.c
30 * @brief UART driver
31 */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif // HAVE_CONFIG_H
36
37 #include "uart.h"
38
39 #include <sys/ioctl.h>
40 #include <sys/select.h>
41 #include <sys/stat.h>
42 #include <sys/time.h>
43 #include <sys/types.h>
44 #include <ctype.h>
45 #include <dirent.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <limits.h>
49 #include <stdio.h>
50 #include <termios.h>
51 #include <unistd.h>
52 #include <stdlib.h>
53
54 #include <nfc/nfc.h>
55 #include "nfc-internal.h"
56
57 #define LOG_GROUP NFC_LOG_GROUP_COM
58 #define LOG_CATEGORY "libnfc.bus.uart"
59
60 #ifndef _WIN32
61 // Needed by sleep() under Unix
62 # include <unistd.h>
63 # include <time.h>
64 # define msleep(x) do { \
65 struct timespec xsleep; \
66 xsleep.tv_sec = x / 1000; \
67 xsleep.tv_nsec = (x - xsleep.tv_sec * 1000) * 1000 * 1000; \
68 nanosleep(&xsleep, NULL); \
69 } while (0)
70 #else
71 // Needed by Sleep() under Windows
72 # include <winbase.h>
73 # define msleep Sleep
74 #endif
75
76 # if defined(__APPLE__)
77 const char *serial_ports_device_radix[] = { "tty.SLAB_USBtoUART", "tty.usbserial-", NULL };
78 # elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__FreeBSD_kernel__)
79 const char *serial_ports_device_radix[] = { "cuaU", "cuau", NULL };
80 # elif defined (__linux__)
81 const char *serial_ports_device_radix[] = { "ttyUSB", "ttyS", "ttyACM", "ttyAMA", "ttyO", NULL };
82 # else
83 # error "Can't determine serial string for your system"
84 # endif
85
86 // Work-around to claim uart interface using the c_iflag (software input processing) from the termios struct
87 # define CCLAIMED 0x80000000
88
89 struct serial_port_unix {
90 int fd; // Serial port file descriptor
91 struct termios termios_backup; // Terminal info before using the port
92 struct termios termios_new; // Terminal info during the transaction
93 };
94
95 #define UART_DATA( X ) ((struct serial_port_unix *) X)
96
97 void uart_close_ext(const serial_port sp, const bool restore_termios);
98
99 serial_port
uart_open(const char * pcPortName)100 uart_open(const char *pcPortName)
101 {
102 struct serial_port_unix *sp = malloc(sizeof(struct serial_port_unix));
103
104 if (sp == 0)
105 return INVALID_SERIAL_PORT;
106
107 sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NONBLOCK);
108 if (sp->fd == -1) {
109 uart_close_ext(sp, false);
110 return INVALID_SERIAL_PORT;
111 }
112
113 if (tcgetattr(sp->fd, &sp->termios_backup) == -1) {
114 uart_close_ext(sp, false);
115 return INVALID_SERIAL_PORT;
116 }
117 // Make sure the port is not claimed already
118 if (sp->termios_backup.c_iflag & CCLAIMED) {
119 uart_close_ext(sp, false);
120 return CLAIMED_SERIAL_PORT;
121 }
122 // Copy the old terminal info struct
123 sp->termios_new = sp->termios_backup;
124
125 sp->termios_new.c_cflag = CS8 | CLOCAL | CREAD;
126 sp->termios_new.c_iflag = CCLAIMED | IGNPAR;
127 sp->termios_new.c_oflag = 0;
128 sp->termios_new.c_lflag = 0;
129
130 sp->termios_new.c_cc[VMIN] = 0; // block until n bytes are received
131 sp->termios_new.c_cc[VTIME] = 0; // block until a timer expires (n * 100 mSec.)
132
133 if (tcsetattr(sp->fd, TCSANOW, &sp->termios_new) == -1) {
134 uart_close_ext(sp, true);
135 return INVALID_SERIAL_PORT;
136 }
137 return sp;
138 }
139
140 void
uart_flush_input(serial_port sp,bool wait)141 uart_flush_input(serial_port sp, bool wait)
142 {
143 // flush commands may seem to be without effect
144 // if asked too quickly after previous event, cf comments below
145 // therefore a "wait" argument allows now to wait before flushing
146 // I believe that now the byte-eater part is not required anymore --Phil
147 if (wait) {
148 msleep(50); // 50 ms
149 }
150
151 // This line seems to produce absolutely no effect on my system (GNU/Linux 2.6.35)
152 tcflush(UART_DATA(sp)->fd, TCIFLUSH);
153 // So, I wrote this byte-eater
154 // Retrieve the count of the incoming bytes
155 int available_bytes_count = 0;
156 int res;
157 res = ioctl(UART_DATA(sp)->fd, FIONREAD, &available_bytes_count);
158 if (res != 0) {
159 return;
160 }
161 if (available_bytes_count == 0) {
162 return;
163 }
164 char *rx = malloc(available_bytes_count);
165 if (!rx) {
166 perror("malloc");
167 return;
168 }
169 // There is something available, read the data
170 if (read(UART_DATA(sp)->fd, rx, available_bytes_count) < 0) {
171 perror("uart read");
172 free(rx);
173 return;
174 }
175 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%d bytes have eaten.", available_bytes_count);
176 free(rx);
177 }
178
179 void
uart_set_speed(serial_port sp,const uint32_t uiPortSpeed)180 uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
181 {
182 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d bauds.", uiPortSpeed);
183
184 // Portability note: on some systems, B9600 != 9600 so we have to do
185 // uint32_t <=> speed_t associations by hand.
186 speed_t stPortSpeed = B9600;
187 switch (uiPortSpeed) {
188 case 9600:
189 stPortSpeed = B9600;
190 break;
191 case 19200:
192 stPortSpeed = B19200;
193 break;
194 case 38400:
195 stPortSpeed = B38400;
196 break;
197 # ifdef B57600
198 case 57600:
199 stPortSpeed = B57600;
200 break;
201 # endif
202 # ifdef B115200
203 case 115200:
204 stPortSpeed = B115200;
205 break;
206 # endif
207 # ifdef B230400
208 case 230400:
209 stPortSpeed = B230400;
210 break;
211 # endif
212 # ifdef B460800
213 case 460800:
214 stPortSpeed = B460800;
215 break;
216 # endif
217 default:
218 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d bauds. Speed value must be one of those defined in termios(3).",
219 uiPortSpeed);
220 return;
221 };
222
223 // Set port speed (Input and Output)
224 cfsetispeed(&(UART_DATA(sp)->termios_new), stPortSpeed);
225 cfsetospeed(&(UART_DATA(sp)->termios_new), stPortSpeed);
226 if (tcsetattr(UART_DATA(sp)->fd, TCSADRAIN, &(UART_DATA(sp)->termios_new)) == -1) {
227 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to apply new speed settings.");
228 }
229 }
230
231 uint32_t
uart_get_speed(serial_port sp)232 uart_get_speed(serial_port sp)
233 {
234 uint32_t uiPortSpeed = 0;
235 switch (cfgetispeed(&UART_DATA(sp)->termios_new)) {
236 case B9600:
237 uiPortSpeed = 9600;
238 break;
239 case B19200:
240 uiPortSpeed = 19200;
241 break;
242 case B38400:
243 uiPortSpeed = 38400;
244 break;
245 # ifdef B57600
246 case B57600:
247 uiPortSpeed = 57600;
248 break;
249 # endif
250 # ifdef B115200
251 case B115200:
252 uiPortSpeed = 115200;
253 break;
254 # endif
255 # ifdef B230400
256 case B230400:
257 uiPortSpeed = 230400;
258 break;
259 # endif
260 # ifdef B460800
261 case B460800:
262 uiPortSpeed = 460800;
263 break;
264 # endif
265 }
266
267 return uiPortSpeed;
268 }
269
270 void
uart_close_ext(const serial_port sp,const bool restore_termios)271 uart_close_ext(const serial_port sp, const bool restore_termios)
272 {
273 if (UART_DATA(sp)->fd >= 0) {
274 if (restore_termios)
275 tcsetattr(UART_DATA(sp)->fd, TCSANOW, &UART_DATA(sp)->termios_backup);
276 close(UART_DATA(sp)->fd);
277 }
278 free(sp);
279 }
280
281 void
uart_close(const serial_port sp)282 uart_close(const serial_port sp)
283 {
284 uart_close_ext(sp, true);
285 }
286
287 /**
288 * @brief Receive data from UART and copy data to \a pbtRx
289 *
290 * @return 0 on success, otherwise driver error code
291 */
292 int
uart_receive(serial_port sp,uint8_t * pbtRx,const size_t szRx,void * abort_p,int timeout)293 uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, int timeout)
294 {
295 int iAbortFd = abort_p ? *((int *)abort_p) : 0;
296 int received_bytes_count = 0;
297 int available_bytes_count = 0;
298 const int expected_bytes_count = (int)szRx;
299 int res;
300 fd_set rfds;
301 do {
302 select:
303 // Reset file descriptor
304 FD_ZERO(&rfds);
305 FD_SET(UART_DATA(sp)->fd, &rfds);
306
307 if (iAbortFd) {
308 FD_SET(iAbortFd, &rfds);
309 }
310
311 struct timeval timeout_tv;
312 if (timeout > 0) {
313 timeout_tv.tv_sec = (timeout / 1000);
314 timeout_tv.tv_usec = ((timeout % 1000) * 1000);
315 }
316
317 res = select(MAX(UART_DATA(sp)->fd, iAbortFd) + 1, &rfds, NULL, NULL, timeout ? &timeout_tv : NULL);
318
319 if ((res < 0) && (EINTR == errno)) {
320 // The system call was interupted by a signal and a signal handler was
321 // run. Restart the interupted system call.
322 goto select;
323 }
324
325 // Read error
326 if (res < 0) {
327 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Error: %s", strerror(errno));
328 return NFC_EIO;
329 }
330 // Read time-out
331 if (res == 0) {
332 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Timeout!");
333 return NFC_ETIMEOUT;
334 }
335
336 if (FD_ISSET(iAbortFd, &rfds)) {
337 // Abort requested
338 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Abort!");
339 close(iAbortFd);
340 return NFC_EOPABORTED;
341 }
342
343 // Retrieve the count of the incoming bytes
344 res = ioctl(UART_DATA(sp)->fd, FIONREAD, &available_bytes_count);
345 if (res != 0) {
346 return NFC_EIO;
347 }
348 // There is something available, read the data
349 res = read(UART_DATA(sp)->fd, pbtRx + received_bytes_count, MIN(available_bytes_count, (expected_bytes_count - received_bytes_count)));
350 // Stop if the OS has some troubles reading the data
351 if (res <= 0) {
352 return NFC_EIO;
353 }
354 received_bytes_count += res;
355
356 } while (expected_bytes_count > received_bytes_count);
357 LOG_HEX(LOG_GROUP, "RX", pbtRx, szRx);
358 return NFC_SUCCESS;
359 }
360
361 /**
362 * @brief Send \a pbtTx content to UART
363 *
364 * @return 0 on success, otherwise a driver error is returned
365 */
366 int
uart_send(serial_port sp,const uint8_t * pbtTx,const size_t szTx,int timeout)367 uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout)
368 {
369 (void) timeout;
370 LOG_HEX(LOG_GROUP, "TX", pbtTx, szTx);
371 if ((int) szTx == write(UART_DATA(sp)->fd, pbtTx, szTx))
372 return NFC_SUCCESS;
373 else
374 return NFC_EIO;
375 }
376
377 char **
uart_list_ports(void)378 uart_list_ports(void)
379 {
380 char **res = malloc(sizeof(char *));
381 if (!res) {
382 perror("malloc");
383 return res;
384 }
385 size_t szRes = 1;
386
387 res[0] = NULL;
388 DIR *dir;
389 if ((dir = opendir("/dev")) == NULL) {
390 perror("opendir error: /dev");
391 return res;
392 }
393 struct dirent entry;
394 struct dirent *result;
395 while ((readdir_r(dir, &entry, &result) == 0) && (result != NULL)) {
396 #if !defined(__APPLE__)
397 if (!isdigit(entry.d_name[strlen(entry.d_name) - 1]))
398 continue;
399 #endif
400 const char **p = serial_ports_device_radix;
401 while (*p) {
402 if (!strncmp(entry.d_name, *p, strlen(*p))) {
403 char **res2 = realloc(res, (szRes + 1) * sizeof(char *));
404 if (!res2) {
405 perror("malloc");
406 goto oom;
407 }
408 res = res2;
409 if (!(res[szRes - 1] = malloc(6 + strlen(entry.d_name)))) {
410 perror("malloc");
411 goto oom;
412 }
413 sprintf(res[szRes - 1], "/dev/%s", entry.d_name);
414
415 szRes++;
416 res[szRes - 1] = NULL;
417 }
418 p++;
419 }
420 }
421 oom:
422 closedir(dir);
423
424 return res;
425 }
426