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 * @file pn532_uart.c
29 * @brief PN532 driver using UART bus (UART, RS232, etc.)
30 */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif // HAVE_CONFIG_H
35
36 #include "pn532_uart.h"
37
38 #include <stdio.h>
39 #include <inttypes.h>
40 #include <string.h>
41 #include <unistd.h>
42
43 #include <nfc/nfc.h>
44
45 #include "drivers.h"
46 #include "nfc-internal.h"
47 #include "chips/pn53x.h"
48 #include "chips/pn53x-internal.h"
49 #include "uart.h"
50
51 #define PN532_UART_DEFAULT_SPEED 115200
52 #define PN532_UART_DRIVER_NAME "pn532_uart"
53
54 #define LOG_CATEGORY "libnfc.driver.pn532_uart"
55 #define LOG_GROUP NFC_LOG_GROUP_DRIVER
56
57 // Internal data structs
58 const struct pn53x_io pn532_uart_io;
59 struct pn532_uart_data {
60 serial_port port;
61 #ifndef WIN32
62 int iAbortFds[2];
63 #else
64 volatile bool abort_flag;
65 #endif
66 };
67
68 // Prototypes
69 int pn532_uart_ack(nfc_device *pnd);
70 int pn532_uart_wakeup(nfc_device *pnd);
71
72 #define DRIVER_DATA(pnd) ((struct pn532_uart_data*)(pnd->driver_data))
73
74 static size_t
pn532_uart_scan(const nfc_context * context,nfc_connstring connstrings[],const size_t connstrings_len)75 pn532_uart_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
76 {
77 size_t device_found = 0;
78 serial_port sp;
79 char **acPorts = uart_list_ports();
80 const char *acPort;
81 int iDevice = 0;
82
83 while ((acPort = acPorts[iDevice++])) {
84 sp = uart_open(acPort);
85 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find PN532 device on serial port: %s at %d bauds.", acPort, PN532_UART_DEFAULT_SPEED);
86
87 if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
88 // We need to flush input to be sure first reply does not comes from older byte transceive
89 uart_flush_input(sp, true);
90 // Serial port claimed but we need to check if a PN532_UART is opened.
91 uart_set_speed(sp, PN532_UART_DEFAULT_SPEED);
92
93 nfc_connstring connstring;
94 snprintf(connstring, sizeof(nfc_connstring), "%s:%s:%"PRIu32, PN532_UART_DRIVER_NAME, acPort, PN532_UART_DEFAULT_SPEED);
95 nfc_device *pnd = nfc_device_new(context, connstring);
96 if (!pnd) {
97 perror("malloc");
98 uart_close(sp);
99 iDevice = 0;
100 while ((acPort = acPorts[iDevice++])) {
101 free((void *)acPort);
102 }
103 free(acPorts);
104 return 0;
105 }
106 pnd->driver = &pn532_uart_driver;
107 pnd->driver_data = malloc(sizeof(struct pn532_uart_data));
108 if (!pnd->driver_data) {
109 perror("malloc");
110 uart_close(sp);
111 nfc_device_free(pnd);
112 iDevice = 0;
113 while ((acPort = acPorts[iDevice++])) {
114 free((void *)acPort);
115 }
116 free(acPorts);
117 return 0;
118 }
119 DRIVER_DATA(pnd)->port = sp;
120
121 // Alloc and init chip's data
122 if (pn53x_data_new(pnd, &pn532_uart_io) == NULL) {
123 perror("malloc");
124 uart_close(DRIVER_DATA(pnd)->port);
125 nfc_device_free(pnd);
126 iDevice = 0;
127 while ((acPort = acPorts[iDevice++])) {
128 free((void *)acPort);
129 }
130 free(acPorts);
131 return 0;
132 }
133 // SAMConfiguration command if needed to wakeup the chip and pn53x_SAMConfiguration check if the chip is a PN532
134 CHIP_DATA(pnd)->type = PN532;
135 // This device starts in LowVBat power mode
136 CHIP_DATA(pnd)->power_mode = LOWVBAT;
137
138 #ifndef WIN32
139 // pipe-based abort mecanism
140 if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
141 uart_close(DRIVER_DATA(pnd)->port);
142 pn53x_data_free(pnd);
143 nfc_device_free(pnd);
144 iDevice = 0;
145 while ((acPort = acPorts[iDevice++])) {
146 free((void *)acPort);
147 }
148 free(acPorts);
149 return 0;
150 }
151 #else
152 DRIVER_DATA(pnd)->abort_flag = false;
153 #endif
154
155 // Check communication using "Diagnose" command, with "Communication test" (0x00)
156 int res = pn53x_check_communication(pnd);
157 uart_close(DRIVER_DATA(pnd)->port);
158 pn53x_data_free(pnd);
159 nfc_device_free(pnd);
160 if (res < 0) {
161 continue;
162 }
163
164 memcpy(connstrings[device_found], connstring, sizeof(nfc_connstring));
165 device_found++;
166
167 // Test if we reach the maximum "wanted" devices
168 if (device_found >= connstrings_len)
169 break;
170 }
171 }
172 iDevice = 0;
173 while ((acPort = acPorts[iDevice++])) {
174 free((void *)acPort);
175 }
176 free(acPorts);
177 return device_found;
178 }
179
180 struct pn532_uart_descriptor {
181 char *port;
182 uint32_t speed;
183 };
184
185 static void
pn532_uart_close(nfc_device * pnd)186 pn532_uart_close(nfc_device *pnd)
187 {
188 pn53x_idle(pnd);
189
190 // Release UART port
191 uart_close(DRIVER_DATA(pnd)->port);
192
193 #ifndef WIN32
194 // Release file descriptors used for abort mecanism
195 close(DRIVER_DATA(pnd)->iAbortFds[0]);
196 close(DRIVER_DATA(pnd)->iAbortFds[1]);
197 #endif
198
199 pn53x_data_free(pnd);
200 nfc_device_free(pnd);
201 }
202
203 static nfc_device *
pn532_uart_open(const nfc_context * context,const nfc_connstring connstring)204 pn532_uart_open(const nfc_context *context, const nfc_connstring connstring)
205 {
206 struct pn532_uart_descriptor ndd;
207 char *speed_s;
208 int connstring_decode_level = connstring_decode(connstring, PN532_UART_DRIVER_NAME, NULL, &ndd.port, &speed_s);
209 if (connstring_decode_level == 3) {
210 ndd.speed = 0;
211 if (sscanf(speed_s, "%10"PRIu32, &ndd.speed) != 1) {
212 // speed_s is not a number
213 free(ndd.port);
214 free(speed_s);
215 return NULL;
216 }
217 free(speed_s);
218 }
219 if (connstring_decode_level < 2) {
220 return NULL;
221 }
222 if (connstring_decode_level < 3) {
223 ndd.speed = PN532_UART_DEFAULT_SPEED;
224 }
225 serial_port sp;
226 nfc_device *pnd = NULL;
227
228 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d bauds.", ndd.port, ndd.speed);
229 sp = uart_open(ndd.port);
230
231 if (sp == INVALID_SERIAL_PORT)
232 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Invalid serial port: %s", ndd.port);
233 if (sp == CLAIMED_SERIAL_PORT)
234 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Serial port already claimed: %s", ndd.port);
235 if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) {
236 free(ndd.port);
237 return NULL;
238 }
239 // We need to flush input to be sure first reply does not comes from older byte transceive
240 uart_flush_input(sp, true);
241 uart_set_speed(sp, ndd.speed);
242
243 // We have a connection
244 pnd = nfc_device_new(context, connstring);
245 if (!pnd) {
246 perror("malloc");
247 free(ndd.port);
248 uart_close(sp);
249 return NULL;
250 }
251 snprintf(pnd->name, sizeof(pnd->name), "%s:%s", PN532_UART_DRIVER_NAME, ndd.port);
252 free(ndd.port);
253
254 pnd->driver_data = malloc(sizeof(struct pn532_uart_data));
255 if (!pnd->driver_data) {
256 perror("malloc");
257 uart_close(sp);
258 nfc_device_free(pnd);
259 return NULL;
260 }
261 DRIVER_DATA(pnd)->port = sp;
262
263 // Alloc and init chip's data
264 if (pn53x_data_new(pnd, &pn532_uart_io) == NULL) {
265 perror("malloc");
266 uart_close(DRIVER_DATA(pnd)->port);
267 nfc_device_free(pnd);
268 return NULL;
269 }
270 // SAMConfiguration command if needed to wakeup the chip and pn53x_SAMConfiguration check if the chip is a PN532
271 CHIP_DATA(pnd)->type = PN532;
272 // This device starts in LowVBat mode
273 CHIP_DATA(pnd)->power_mode = LOWVBAT;
274
275 // empirical tuning
276 CHIP_DATA(pnd)->timer_correction = 48;
277 pnd->driver = &pn532_uart_driver;
278
279 #ifndef WIN32
280 // pipe-based abort mecanism
281 if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
282 uart_close(DRIVER_DATA(pnd)->port);
283 pn53x_data_free(pnd);
284 nfc_device_free(pnd);
285 return NULL;
286 }
287 #else
288 DRIVER_DATA(pnd)->abort_flag = false;
289 #endif
290
291 // Check communication using "Diagnose" command, with "Communication test" (0x00)
292 if (pn53x_check_communication(pnd) < 0) {
293 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "pn53x_check_communication error");
294 pn532_uart_close(pnd);
295 return NULL;
296 }
297
298 pn53x_init(pnd);
299 return pnd;
300 }
301
302 int
pn532_uart_wakeup(nfc_device * pnd)303 pn532_uart_wakeup(nfc_device *pnd)
304 {
305 /* High Speed Unit (HSU) wake up consist to send 0x55 and wait a "long" delay for PN532 being wakeup. */
306 const uint8_t pn532_wakeup_preamble[] = { 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
307 int res = uart_send(DRIVER_DATA(pnd)->port, pn532_wakeup_preamble, sizeof(pn532_wakeup_preamble), 0);
308 CHIP_DATA(pnd)->power_mode = NORMAL; // PN532 should now be awake
309 return res;
310 }
311
312 #define PN532_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
313 static int
pn532_uart_send(nfc_device * pnd,const uint8_t * pbtData,const size_t szData,int timeout)314 pn532_uart_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout)
315 {
316 int res = 0;
317 // Before sending anything, we need to discard from any junk bytes
318 uart_flush_input(DRIVER_DATA(pnd)->port, false);
319
320 switch (CHIP_DATA(pnd)->power_mode) {
321 case LOWVBAT: {
322 /** PN532C106 wakeup. */
323 if ((res = pn532_uart_wakeup(pnd)) < 0) {
324 return res;
325 }
326 // According to PN532 application note, C106 appendix: to go out Low Vbat mode and enter in normal mode we need to send a SAMConfiguration command
327 if ((res = pn532_SAMConfiguration(pnd, PSM_NORMAL, 1000)) < 0) {
328 return res;
329 }
330 }
331 break;
332 case POWERDOWN: {
333 if ((res = pn532_uart_wakeup(pnd)) < 0) {
334 return res;
335 }
336 }
337 break;
338 case NORMAL:
339 // Nothing to do :)
340 break;
341 };
342
343 uint8_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
344 size_t szFrame = 0;
345
346 if ((res = pn53x_build_frame(abtFrame, &szFrame, pbtData, szData)) < 0) {
347 pnd->last_error = res;
348 return pnd->last_error;
349 }
350
351 res = uart_send(DRIVER_DATA(pnd)->port, abtFrame, szFrame, timeout);
352 if (res != 0) {
353 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
354 pnd->last_error = res;
355 return pnd->last_error;
356 }
357
358 uint8_t abtRxBuf[PN53x_ACK_FRAME__LEN];
359 res = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, sizeof(abtRxBuf), 0, timeout);
360 if (res != 0) {
361 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Unable to read ACK");
362 pnd->last_error = res;
363 return pnd->last_error;
364 }
365
366 if (pn53x_check_ack_frame(pnd, abtRxBuf, sizeof(abtRxBuf)) == 0) {
367 // The PN53x is running the sent command
368 } else {
369 return pnd->last_error;
370 }
371 return NFC_SUCCESS;
372 }
373
374 static int
pn532_uart_receive(nfc_device * pnd,uint8_t * pbtData,const size_t szDataLen,int timeout)375 pn532_uart_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int timeout)
376 {
377 uint8_t abtRxBuf[5];
378 size_t len;
379 void *abort_p = NULL;
380
381 #ifndef WIN32
382 abort_p = &(DRIVER_DATA(pnd)->iAbortFds[1]);
383 #else
384 abort_p = (void *) & (DRIVER_DATA(pnd)->abort_flag);
385 #endif
386
387 pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 5, abort_p, timeout);
388
389 if (abort_p && (NFC_EOPABORTED == pnd->last_error)) {
390 pn532_uart_ack(pnd);
391 return NFC_EOPABORTED;
392 }
393
394 if (pnd->last_error < 0) {
395 goto error;
396 }
397
398 const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
399 if (0 != (memcmp(abtRxBuf, pn53x_preamble, 3))) {
400 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
401 pnd->last_error = NFC_EIO;
402 goto error;
403 }
404
405 if ((0x01 == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
406 // Error frame
407 uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 3, 0, timeout);
408 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Application level error detected");
409 pnd->last_error = NFC_EIO;
410 goto error;
411 } else if ((0xff == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
412 // Extended frame
413 pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 3, 0, timeout);
414 if (pnd->last_error != 0) {
415 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
416 goto error;
417 }
418 // (abtRxBuf[0] << 8) + abtRxBuf[1] (LEN) include TFI + (CC+1)
419 len = (abtRxBuf[0] << 8) + abtRxBuf[1] - 2;
420 if (((abtRxBuf[0] + abtRxBuf[1] + abtRxBuf[2]) % 256) != 0) {
421 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
422 pnd->last_error = NFC_EIO;
423 goto error;
424 }
425 } else {
426 // Normal frame
427 if (256 != (abtRxBuf[3] + abtRxBuf[4])) {
428 // TODO: Retry
429 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
430 pnd->last_error = NFC_EIO;
431 goto error;
432 }
433
434 // abtRxBuf[3] (LEN) include TFI + (CC+1)
435 len = abtRxBuf[3] - 2;
436 }
437
438 if (len > szDataLen) {
439 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to receive data: buffer too small. (szDataLen: %" PRIuPTR ", len: %" PRIuPTR ")", szDataLen, len);
440 pnd->last_error = NFC_EIO;
441 goto error;
442 }
443
444 // TFI + PD0 (CC+1)
445 pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 2, 0, timeout);
446 if (pnd->last_error != 0) {
447 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
448 goto error;
449 }
450
451 if (abtRxBuf[0] != 0xD5) {
452 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "TFI Mismatch");
453 pnd->last_error = NFC_EIO;
454 goto error;
455 }
456
457 if (abtRxBuf[1] != CHIP_DATA(pnd)->last_command + 1) {
458 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Command Code verification failed");
459 pnd->last_error = NFC_EIO;
460 goto error;
461 }
462
463 if (len) {
464 pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, pbtData, len, 0, timeout);
465 if (pnd->last_error != 0) {
466 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
467 goto error;
468 }
469 }
470
471 pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 2, 0, timeout);
472 if (pnd->last_error != 0) {
473 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
474 goto error;
475 }
476
477 uint8_t btDCS = (256 - 0xD5);
478 btDCS -= CHIP_DATA(pnd)->last_command + 1;
479 for (size_t szPos = 0; szPos < len; szPos++) {
480 btDCS -= pbtData[szPos];
481 }
482
483 if (btDCS != abtRxBuf[0]) {
484 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Data checksum mismatch");
485 pnd->last_error = NFC_EIO;
486 goto error;
487 }
488
489 if (0x00 != abtRxBuf[1]) {
490 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame postamble mismatch");
491 pnd->last_error = NFC_EIO;
492 goto error;
493 }
494 // The PN53x command is done and we successfully received the reply
495 return len;
496 error:
497 uart_flush_input(DRIVER_DATA(pnd)->port, true);
498 return pnd->last_error;
499 }
500
501 int
pn532_uart_ack(nfc_device * pnd)502 pn532_uart_ack(nfc_device *pnd)
503 {
504 if (POWERDOWN == CHIP_DATA(pnd)->power_mode) {
505 int res = 0;
506 if ((res = pn532_uart_wakeup(pnd)) < 0) {
507 return res;
508 }
509 }
510 return (uart_send(DRIVER_DATA(pnd)->port, pn53x_ack_frame, sizeof(pn53x_ack_frame), 0));
511 }
512
513 static int
pn532_uart_abort_command(nfc_device * pnd)514 pn532_uart_abort_command(nfc_device *pnd)
515 {
516 if (pnd) {
517 #ifndef WIN32
518 close(DRIVER_DATA(pnd)->iAbortFds[0]);
519 if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
520 return NFC_ESOFT;
521 }
522 #else
523 DRIVER_DATA(pnd)->abort_flag = true;
524 #endif
525 }
526 return NFC_SUCCESS;
527 }
528
529 const struct pn53x_io pn532_uart_io = {
530 .send = pn532_uart_send,
531 .receive = pn532_uart_receive,
532 };
533
534 const struct nfc_driver pn532_uart_driver = {
535 .name = PN532_UART_DRIVER_NAME,
536 .scan_type = INTRUSIVE,
537 .scan = pn532_uart_scan,
538 .open = pn532_uart_open,
539 .close = pn532_uart_close,
540 .strerror = pn53x_strerror,
541
542 .initiator_init = pn53x_initiator_init,
543 .initiator_init_secure_element = pn532_initiator_init_secure_element,
544 .initiator_select_passive_target = pn53x_initiator_select_passive_target,
545 .initiator_poll_target = pn53x_initiator_poll_target,
546 .initiator_select_dep_target = pn53x_initiator_select_dep_target,
547 .initiator_deselect_target = pn53x_initiator_deselect_target,
548 .initiator_transceive_bytes = pn53x_initiator_transceive_bytes,
549 .initiator_transceive_bits = pn53x_initiator_transceive_bits,
550 .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed,
551 .initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed,
552 .initiator_target_is_present = pn53x_initiator_target_is_present,
553
554 .target_init = pn53x_target_init,
555 .target_send_bytes = pn53x_target_send_bytes,
556 .target_receive_bytes = pn53x_target_receive_bytes,
557 .target_send_bits = pn53x_target_send_bits,
558 .target_receive_bits = pn53x_target_receive_bits,
559
560 .device_set_property_bool = pn53x_set_property_bool,
561 .device_set_property_int = pn53x_set_property_int,
562 .get_supported_modulation = pn53x_get_supported_modulation,
563 .get_supported_baud_rate = pn53x_get_supported_baud_rate,
564 .device_get_information_about = pn53x_get_information_about,
565
566 .abort_command = pn532_uart_abort_command,
567 .idle = pn53x_idle,
568 .powerdown = pn53x_PowerDown,
569 };
570
571