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 arygon.c
29  * @brief ARYGON readers driver
30  *
31  * This driver can handle ARYGON readers that use UART as bus.
32  * UART connection can be direct (host<->arygon_uc) or could be provided by internal USB to serial interface (e.g. host<->ftdi_chip<->arygon_uc)
33  */
34 
35 #ifdef HAVE_CONFIG_H
36 #  include "config.h"
37 #endif // HAVE_CONFIG_H
38 
39 #include "arygon.h"
40 
41 #include <stdio.h>
42 #include <inttypes.h>
43 #include <string.h>
44 #include <string.h>
45 #include <unistd.h>
46 
47 #include <nfc/nfc.h>
48 
49 #include "drivers.h"
50 #include "nfc-internal.h"
51 #include "chips/pn53x.h"
52 #include "chips/pn53x-internal.h"
53 #include "uart.h"
54 
55 /** @def DEV_ARYGON_PROTOCOL_ARYGON_ASCII
56  * @brief High level language in ASCII format. (Common µC commands and Mifare® commands)
57  */
58 #define DEV_ARYGON_PROTOCOL_ARYGON_ASCII        '0'
59 /** @def DEV_ARYGON_MODE_HL_ASCII
60  * @brief High level language in Binary format With AddressingByte for party line. (Common µC commands and Mifare® commands)
61  */
62 #define DEV_ARYGON_PROTOCOL_ARYGON_BINARY_WAB   '1'
63 /** @def DEV_ARYGON_PROTOCOL_TAMA
64  * @brief Philips protocol (TAMA language) in binary format.
65  */
66 #define DEV_ARYGON_PROTOCOL_TAMA                '2'
67 /** @def DEV_ARYGON_PROTOCOL_TAMA_WAB
68  * @brief Philips protocol (TAMA language) in binary With AddressingByte for party line.
69  */
70 #define DEV_ARYGON_PROTOCOL_TAMA_WAB            '3'
71 
72 #define ARYGON_DEFAULT_SPEED 9600
73 #define ARYGON_DRIVER_NAME "arygon"
74 
75 #define LOG_CATEGORY "libnfc.driver.arygon"
76 #define LOG_GROUP     NFC_LOG_GROUP_DRIVER
77 
78 #define DRIVER_DATA(pnd) ((struct arygon_data*)(pnd->driver_data))
79 
80 // Internal data structs
81 const struct pn53x_io arygon_tama_io;
82 
83 struct arygon_data {
84   serial_port port;
85 #ifndef WIN32
86   int     iAbortFds[2];
87 #else
88   volatile bool abort_flag;
89 #endif
90 };
91 
92 // ARYGON frames
93 static const uint8_t arygon_error_none[] = "FF000000\x0d\x0a";
94 static const uint8_t arygon_error_incomplete_command[] = "FF0C0000\x0d\x0a";
95 static const uint8_t arygon_error_unknown_mode[] = "FF060000\x0d\x0a";
96 
97 // Prototypes
98 int     arygon_reset_tama(nfc_device *pnd);
99 void    arygon_firmware(nfc_device *pnd, char *str);
100 
101 static size_t
arygon_scan(const nfc_context * context,nfc_connstring connstrings[],const size_t connstrings_len)102 arygon_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
103 {
104   size_t device_found = 0;
105   serial_port sp;
106   char **acPorts = uart_list_ports();
107   const char *acPort;
108   int     iDevice = 0;
109 
110   while ((acPort = acPorts[iDevice++])) {
111     sp = uart_open(acPort);
112     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find ARYGON device on serial port: %s at %d bauds.", acPort, ARYGON_DEFAULT_SPEED);
113 
114     if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
115       // We need to flush input to be sure first reply does not comes from older byte transceive
116       uart_flush_input(sp, true);
117       uart_set_speed(sp, ARYGON_DEFAULT_SPEED);
118 
119       nfc_connstring connstring;
120       snprintf(connstring, sizeof(nfc_connstring), "%s:%s:%"PRIu32, ARYGON_DRIVER_NAME, acPort, ARYGON_DEFAULT_SPEED);
121       nfc_device *pnd = nfc_device_new(context, connstring);
122       if (!pnd) {
123         perror("malloc");
124         uart_close(sp);
125         iDevice = 0;
126         while ((acPort = acPorts[iDevice++])) {
127           free((void *)acPort);
128         }
129         free(acPorts);
130         return 0;
131       }
132 
133       pnd->driver = &arygon_driver;
134       pnd->driver_data = malloc(sizeof(struct arygon_data));
135       if (!pnd->driver_data) {
136         perror("malloc");
137         uart_close(sp);
138         nfc_device_free(pnd);
139         iDevice = 0;
140         while ((acPort = acPorts[iDevice++])) {
141           free((void *)acPort);
142         }
143         free(acPorts);
144         return 0;
145       }
146       DRIVER_DATA(pnd)->port = sp;
147 
148       // Alloc and init chip's data
149       if (pn53x_data_new(pnd, &arygon_tama_io) == NULL) {
150         perror("malloc");
151         uart_close(DRIVER_DATA(pnd)->port);
152         nfc_device_free(pnd);
153         iDevice = 0;
154         while ((acPort = acPorts[iDevice++])) {
155           free((void *)acPort);
156         }
157         free(acPorts);
158         return 0;
159       }
160 
161 #ifndef WIN32
162       // pipe-based abort mecanism
163       if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
164         uart_close(DRIVER_DATA(pnd)->port);
165         pn53x_data_free(pnd);
166         nfc_device_free(pnd);
167         iDevice = 0;
168         while ((acPort = acPorts[iDevice++])) {
169           free((void *)acPort);
170         }
171         free(acPorts);
172         return 0;
173       }
174 #else
175       DRIVER_DATA(pnd)->abort_flag = false;
176 #endif
177 
178       int res = arygon_reset_tama(pnd);
179       uart_close(DRIVER_DATA(pnd)->port);
180       pn53x_data_free(pnd);
181       nfc_device_free(pnd);
182       if (res < 0) {
183         continue;
184       }
185 
186       // ARYGON reader is found
187       memcpy(connstrings[device_found], connstring, sizeof(nfc_connstring));
188       device_found++;
189 
190       // Test if we reach the maximum "wanted" devices
191       if (device_found >= connstrings_len)
192         break;
193     }
194   }
195   iDevice = 0;
196   while ((acPort = acPorts[iDevice++])) {
197     free((void *)acPort);
198   }
199   free(acPorts);
200   return device_found;
201 }
202 
203 struct arygon_descriptor {
204   char *port;
205   uint32_t speed;
206 };
207 
208 static void
arygon_close_step2(nfc_device * pnd)209 arygon_close_step2(nfc_device *pnd)
210 {
211   // Release UART port
212   uart_close(DRIVER_DATA(pnd)->port);
213 
214 #ifndef WIN32
215   // Release file descriptors used for abort mecanism
216   close(DRIVER_DATA(pnd)->iAbortFds[0]);
217   close(DRIVER_DATA(pnd)->iAbortFds[1]);
218 #endif
219 
220   pn53x_data_free(pnd);
221   nfc_device_free(pnd);
222 }
223 
224 static void
arygon_close(nfc_device * pnd)225 arygon_close(nfc_device *pnd)
226 {
227   pn53x_idle(pnd);
228   arygon_close_step2(pnd);
229 }
230 
231 static nfc_device *
arygon_open(const nfc_context * context,const nfc_connstring connstring)232 arygon_open(const nfc_context *context, const nfc_connstring connstring)
233 {
234   struct arygon_descriptor ndd;
235   char *speed_s;
236   int connstring_decode_level = connstring_decode(connstring, ARYGON_DRIVER_NAME, NULL, &ndd.port, &speed_s);
237   if (connstring_decode_level == 3) {
238     ndd.speed = 0;
239     if (sscanf(speed_s, "%10"PRIu32, &ndd.speed) != 1) {
240       // speed_s is not a number
241       free(ndd.port);
242       free(speed_s);
243       return NULL;
244     }
245     free(speed_s);
246   }
247   if (connstring_decode_level < 2) {
248     return NULL;
249   }
250   if (connstring_decode_level < 3) {
251     ndd.speed = ARYGON_DEFAULT_SPEED;
252   }
253   serial_port sp;
254   nfc_device *pnd = NULL;
255 
256   log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d bauds.", ndd.port, ndd.speed);
257   sp = uart_open(ndd.port);
258 
259   if (sp == INVALID_SERIAL_PORT)
260     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Invalid serial port: %s", ndd.port);
261   if (sp == CLAIMED_SERIAL_PORT)
262     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Serial port already claimed: %s", ndd.port);
263   if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT)) {
264     free(ndd.port);
265     return NULL;
266   }
267 
268   // We need to flush input to be sure first reply does not comes from older byte transceive
269   uart_flush_input(sp, true);
270   uart_set_speed(sp, ndd.speed);
271 
272   // We have a connection
273   pnd = nfc_device_new(context, connstring);
274   if (!pnd) {
275     perror("malloc");
276     free(ndd.port);
277     uart_close(sp);
278     return NULL;
279   }
280   snprintf(pnd->name, sizeof(pnd->name), "%s:%s", ARYGON_DRIVER_NAME, ndd.port);
281   free(ndd.port);
282 
283   pnd->driver_data = malloc(sizeof(struct arygon_data));
284   if (!pnd->driver_data) {
285     perror("malloc");
286     uart_close(sp);
287     nfc_device_free(pnd);
288     return NULL;
289   }
290   DRIVER_DATA(pnd)->port = sp;
291 
292   // Alloc and init chip's data
293   if (pn53x_data_new(pnd, &arygon_tama_io) == NULL) {
294     perror("malloc");
295     uart_close(DRIVER_DATA(pnd)->port);
296     nfc_device_free(pnd);
297     return NULL;
298   }
299 
300   // The PN53x chip opened to ARYGON MCU doesn't seems to be in LowVBat mode
301   CHIP_DATA(pnd)->power_mode = NORMAL;
302 
303   // empirical tuning
304   CHIP_DATA(pnd)->timer_correction = 46;
305   pnd->driver = &arygon_driver;
306 
307 #ifndef WIN32
308   // pipe-based abort mecanism
309   if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
310     uart_close(DRIVER_DATA(pnd)->port);
311     pn53x_data_free(pnd);
312     nfc_device_free(pnd);
313     return NULL;
314   }
315 #else
316   DRIVER_DATA(pnd)->abort_flag = false;
317 #endif
318 
319   // Check communication using "Reset TAMA" command
320   if (arygon_reset_tama(pnd) < 0) {
321     arygon_close_step2(pnd);
322     return NULL;
323   }
324 
325   char arygon_firmware_version[10];
326   arygon_firmware(pnd, arygon_firmware_version);
327   char   *pcName;
328   pcName = strdup(pnd->name);
329   snprintf(pnd->name, sizeof(pnd->name), "%s %s", pcName, arygon_firmware_version);
330   free(pcName);
331 
332   pn53x_init(pnd);
333   return pnd;
334 }
335 
336 #define ARYGON_TX_BUFFER_LEN (PN53x_NORMAL_FRAME__DATA_MAX_LEN + PN53x_NORMAL_FRAME__OVERHEAD + 1)
337 #define ARYGON_RX_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
338 static int
arygon_tama_send(nfc_device * pnd,const uint8_t * pbtData,const size_t szData,int timeout)339 arygon_tama_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout)
340 {
341   int res = 0;
342   // Before sending anything, we need to discard from any junk bytes
343   uart_flush_input(DRIVER_DATA(pnd)->port, false);
344 
345   uint8_t abtFrame[ARYGON_TX_BUFFER_LEN] = { DEV_ARYGON_PROTOCOL_TAMA, 0x00, 0x00, 0xff };     // Every packet must start with "0x32 0x00 0x00 0xff"
346 
347   size_t szFrame = 0;
348   if (szData > PN53x_NORMAL_FRAME__DATA_MAX_LEN) {
349     // ARYGON Reader with PN532 equipped does not support extended frame (bug in ARYGON firmware?)
350     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ARYGON device does not support more than %d bytes as payload (requested: %" PRIdPTR ")", PN53x_NORMAL_FRAME__DATA_MAX_LEN, szData);
351     pnd->last_error = NFC_EDEVNOTSUPP;
352     return pnd->last_error;
353   }
354 
355   if ((res = pn53x_build_frame(abtFrame + 1, &szFrame, pbtData, szData)) < 0) {
356     pnd->last_error = res;
357     return pnd->last_error;
358   }
359 
360   if ((res = uart_send(DRIVER_DATA(pnd)->port, abtFrame, szFrame + 1, timeout)) != 0) {
361     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
362     pnd->last_error = res;
363     return pnd->last_error;
364   }
365 
366   uint8_t abtRxBuf[PN53x_ACK_FRAME__LEN];
367   if ((res = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, sizeof(abtRxBuf), 0, timeout)) != 0) {
368     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to read ACK");
369     pnd->last_error = res;
370     return pnd->last_error;
371   }
372 
373   if (pn53x_check_ack_frame(pnd, abtRxBuf, sizeof(abtRxBuf)) == 0) {
374     // The PN53x is running the sent command
375   } else if (0 == memcmp(arygon_error_unknown_mode, abtRxBuf, sizeof(abtRxBuf))) {
376     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Bad frame format.");
377     // We have already read 6 bytes and arygon_error_unknown_mode is 10 bytes long
378     // so we have to read 4 remaining bytes to be synchronized at the next receiving pass.
379     pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 4, 0, timeout);
380     return pnd->last_error;
381   } else {
382     return pnd->last_error;
383   }
384   return NFC_SUCCESS;
385 }
386 
387 static int
arygon_abort(nfc_device * pnd)388 arygon_abort(nfc_device *pnd)
389 {
390   // Send a valid TAMA packet to wakup the PN53x (we will not have an answer, according to Arygon manual)
391   uint8_t dummy[] = { 0x32, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0xbe, 0x00 };
392 
393   uart_send(DRIVER_DATA(pnd)->port, dummy, sizeof(dummy), 0);
394 
395   // Using Arygon device we can't send ACK frame to abort the running command
396   return pn53x_check_communication(pnd);
397 }
398 
399 static int
arygon_tama_receive(nfc_device * pnd,uint8_t * pbtData,const size_t szDataLen,int timeout)400 arygon_tama_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int timeout)
401 {
402   uint8_t  abtRxBuf[5];
403   size_t len;
404   void *abort_p = NULL;
405 
406 #ifndef WIN32
407   abort_p = &(DRIVER_DATA(pnd)->iAbortFds[1]);
408 #else
409   abort_p = (void *) & (DRIVER_DATA(pnd)->abort_flag);
410 #endif
411 
412   pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 5, abort_p, timeout);
413 
414   if (abort_p && (NFC_EOPABORTED == pnd->last_error)) {
415     arygon_abort(pnd);
416 
417     /* last_error got reset by arygon_abort() */
418     pnd->last_error = NFC_EOPABORTED;
419     return pnd->last_error;
420   }
421 
422   if (pnd->last_error != 0) {
423     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
424     return pnd->last_error;
425   }
426 
427   const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
428   if (0 != (memcmp(abtRxBuf, pn53x_preamble, 3))) {
429     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
430     pnd->last_error = NFC_EIO;
431     return pnd->last_error;
432   }
433 
434   if ((0x01 == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
435     // Error frame
436     uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 3, 0, timeout);
437     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Application level error detected");
438     pnd->last_error = NFC_EIO;
439     return pnd->last_error;
440   } else if ((0xff == abtRxBuf[3]) && (0xff == abtRxBuf[4])) {
441     // Extended frame
442     // ARYGON devices does not support extended frame sending
443     abort();
444   } else {
445     // Normal frame
446     if (256 != (abtRxBuf[3] + abtRxBuf[4])) {
447       // TODO: Retry
448       log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
449       pnd->last_error = NFC_EIO;
450       return pnd->last_error;
451     }
452 
453     // abtRxBuf[3] (LEN) include TFI + (CC+1)
454     len = abtRxBuf[3] - 2;
455   }
456 
457   if (len > szDataLen) {
458     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to receive data: buffer too small. (szDataLen: %" PRIuPTR ", len: %" PRIuPTR ")", szDataLen, len);
459     pnd->last_error = NFC_EIO;
460     return pnd->last_error;
461   }
462 
463   // TFI + PD0 (CC+1)
464   pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 2, 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     return pnd->last_error;
468   }
469 
470   if (abtRxBuf[0] != 0xD5) {
471     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "TFI Mismatch");
472     pnd->last_error = NFC_EIO;
473     return pnd->last_error;
474   }
475 
476   if (abtRxBuf[1] != CHIP_DATA(pnd)->last_command + 1) {
477     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Command Code verification failed");
478     pnd->last_error = NFC_EIO;
479     return pnd->last_error;
480   }
481 
482   if (len) {
483     pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, pbtData, len, 0, timeout);
484     if (pnd->last_error != 0) {
485       log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
486       return pnd->last_error;
487     }
488   }
489 
490   pnd->last_error = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 2, 0, timeout);
491   if (pnd->last_error != 0) {
492     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
493     return pnd->last_error;
494   }
495 
496   uint8_t btDCS = (256 - 0xD5);
497   btDCS -= CHIP_DATA(pnd)->last_command + 1;
498   for (size_t szPos = 0; szPos < len; szPos++) {
499     btDCS -= pbtData[szPos];
500   }
501 
502   if (btDCS != abtRxBuf[0]) {
503     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Data checksum mismatch");
504     pnd->last_error = NFC_EIO;
505     return pnd->last_error;
506   }
507 
508   if (0x00 != abtRxBuf[1]) {
509     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame postamble mismatch");
510     pnd->last_error = NFC_EIO;
511     return pnd->last_error;
512   }
513   // The PN53x command is done and we successfully received the reply
514   return len;
515 }
516 
517 void
arygon_firmware(nfc_device * pnd,char * str)518 arygon_firmware(nfc_device *pnd, char *str)
519 {
520   const uint8_t arygon_firmware_version_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'v' };
521   uint8_t abtRx[16];
522   size_t szRx = sizeof(abtRx);
523 
524 
525   int res = uart_send(DRIVER_DATA(pnd)->port, arygon_firmware_version_cmd, sizeof(arygon_firmware_version_cmd), 0);
526   if (res != 0) {
527     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Unable to send ARYGON firmware command.");
528     return;
529   }
530   res = uart_receive(DRIVER_DATA(pnd)->port, abtRx, szRx, 0, 0);
531   if (res != 0) {
532     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Unable to retrieve ARYGON firmware version.");
533     return;
534   }
535 
536   if (0 == memcmp(abtRx, arygon_error_none, 6)) {
537     uint8_t *p = abtRx + 6;
538     unsigned int szData;
539     sscanf((const char *)p, "%02x%9s", &szData, p);
540     if (szData > 9)
541       szData = 9;
542     memcpy(str, p, szData);
543     *(str + szData) = '\0';
544   }
545 }
546 
547 int
arygon_reset_tama(nfc_device * pnd)548 arygon_reset_tama(nfc_device *pnd)
549 {
550   const uint8_t arygon_reset_tama_cmd[] = { DEV_ARYGON_PROTOCOL_ARYGON_ASCII, 'a', 'r' };
551   uint8_t abtRx[10]; // Attempted response is 10 bytes long
552   size_t szRx = sizeof(abtRx);
553   int res;
554 
555   uart_send(DRIVER_DATA(pnd)->port, arygon_reset_tama_cmd, sizeof(arygon_reset_tama_cmd), 500);
556 
557   // Two reply are possible from ARYGON device: arygon_error_none (ie. in case the byte is well-sent)
558   // or arygon_error_unknown_mode (ie. in case of the first byte was bad-transmitted)
559   res = uart_receive(DRIVER_DATA(pnd)->port, abtRx, szRx, 0, 1000);
560   if (res != 0) {
561     log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "No reply to 'reset TAMA' command.");
562     pnd->last_error = res;
563     return pnd->last_error;
564   }
565 
566   if (0 != memcmp(abtRx, arygon_error_none, sizeof(arygon_error_none) - 1)) {
567     pnd->last_error = NFC_EIO;
568     return pnd->last_error;
569   }
570 
571   return NFC_SUCCESS;
572 }
573 
574 static int
arygon_abort_command(nfc_device * pnd)575 arygon_abort_command(nfc_device *pnd)
576 {
577   if (pnd) {
578 #ifndef WIN32
579     close(DRIVER_DATA(pnd)->iAbortFds[0]);
580     if (pipe(DRIVER_DATA(pnd)->iAbortFds) < 0) {
581       return NFC_ESOFT;
582     }
583 #else
584     DRIVER_DATA(pnd)->abort_flag = true;
585 #endif
586   }
587   return NFC_SUCCESS;
588 }
589 
590 
591 const struct pn53x_io arygon_tama_io = {
592   .send       = arygon_tama_send,
593   .receive    = arygon_tama_receive,
594 };
595 
596 const struct nfc_driver arygon_driver = {
597   .name                             = ARYGON_DRIVER_NAME,
598   .scan_type                        = INTRUSIVE,
599   .scan                             = arygon_scan,
600   .open                             = arygon_open,
601   .close                            = arygon_close,
602   .strerror                         = pn53x_strerror,
603 
604   .initiator_init                   = pn53x_initiator_init,
605   .initiator_init_secure_element    = NULL, // No secure-element support
606   .initiator_select_passive_target  = pn53x_initiator_select_passive_target,
607   .initiator_poll_target            = pn53x_initiator_poll_target,
608   .initiator_select_dep_target      = pn53x_initiator_select_dep_target,
609   .initiator_deselect_target        = pn53x_initiator_deselect_target,
610   .initiator_transceive_bytes       = pn53x_initiator_transceive_bytes,
611   .initiator_transceive_bits        = pn53x_initiator_transceive_bits,
612   .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed,
613   .initiator_transceive_bits_timed  = pn53x_initiator_transceive_bits_timed,
614   .initiator_target_is_present      = pn53x_initiator_target_is_present,
615 
616   .target_init           = pn53x_target_init,
617   .target_send_bytes     = pn53x_target_send_bytes,
618   .target_receive_bytes  = pn53x_target_receive_bytes,
619   .target_send_bits      = pn53x_target_send_bits,
620   .target_receive_bits   = pn53x_target_receive_bits,
621 
622   .device_set_property_bool     = pn53x_set_property_bool,
623   .device_set_property_int      = pn53x_set_property_int,
624   .get_supported_modulation     = pn53x_get_supported_modulation,
625   .get_supported_baud_rate      = pn53x_get_supported_baud_rate,
626   .device_get_information_about = pn53x_get_information_about,
627 
628   .abort_command  = arygon_abort_command,
629   .idle           = pn53x_idle,
630   /* Even if PN532, PowerDown is not recommended on those devices */
631   .powerdown      = NULL,
632 };
633 
634