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 * Copyright (C) 2013 Evgeny Boger
13 *
14 * This program is free software: you can redistribute it and/or modify it
15 * under the terms of the GNU Lesser General Public License as published by the
16 * Free Software Foundation, either version 3 of the License, or (at your
17 * option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 * more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with this program. If not, see <http://www.gnu.org/licenses/>
26 */
27
28 /**
29 * @file pn532_spi.c
30 * @brief PN532 driver using SPI bus
31 */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif // HAVE_CONFIG_H
36
37 #include "pn532_spi.h"
38
39 #include <stdio.h>
40 #include <inttypes.h>
41 #include <string.h>
42 #include <nfc/nfc.h>
43
44 #include "drivers.h"
45 #include "nfc-internal.h"
46 #include "chips/pn53x.h"
47 #include "chips/pn53x-internal.h"
48 #include "spi.h"
49
50 #define PN532_SPI_DEFAULT_SPEED 1000000 // 1 MHz
51 #define PN532_SPI_DRIVER_NAME "pn532_spi"
52 #define PN532_SPI_MODE SPI_MODE_0
53
54 #define LOG_CATEGORY "libnfc.driver.pn532_spi"
55 #define LOG_GROUP NFC_LOG_GROUP_DRIVER
56
57 #ifndef _WIN32
58 // Needed by sleep() under Unix
59 # include <unistd.h>
60 # include <time.h>
61 # define msleep(x) do { \
62 struct timespec xsleep; \
63 xsleep.tv_sec = x / 1000; \
64 xsleep.tv_nsec = (x - xsleep.tv_sec * 1000) * 1000 * 1000; \
65 nanosleep(&xsleep, NULL); \
66 } while (0)
67 #else
68 // Needed by Sleep() under Windows
69 # include <winbase.h>
70 # define msleep Sleep
71 #endif
72
73 // Internal data structs
74 const struct pn53x_io pn532_spi_io;
75 struct pn532_spi_data {
76 spi_port port;
77 volatile bool abort_flag;
78 };
79
80 static const uint8_t pn532_spi_cmd_dataread = 0x03;
81 static const uint8_t pn532_spi_cmd_datawrite = 0x01;
82
83
84 // Prototypes
85 int pn532_spi_ack(nfc_device *pnd);
86 int pn532_spi_wakeup(nfc_device *pnd);
87
88 #define DRIVER_DATA(pnd) ((struct pn532_spi_data*)(pnd->driver_data))
89
90 static size_t
pn532_spi_scan(const nfc_context * context,nfc_connstring connstrings[],const size_t connstrings_len)91 pn532_spi_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
92 {
93 size_t device_found = 0;
94 spi_port sp;
95 char **acPorts = spi_list_ports();
96 const char *acPort;
97 int iDevice = 0;
98
99 while ((acPort = acPorts[iDevice++])) {
100 sp = spi_open(acPort);
101 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find PN532 device on SPI port: %s at %d Hz.", acPort, PN532_SPI_DEFAULT_SPEED);
102
103 if ((sp != INVALID_SPI_PORT) && (sp != CLAIMED_SPI_PORT)) {
104 // Serial port claimed but we need to check if a PN532_SPI is opened.
105 spi_set_speed(sp, PN532_SPI_DEFAULT_SPEED);
106 spi_set_mode(sp, PN532_SPI_MODE);
107
108 nfc_connstring connstring;
109 snprintf(connstring, sizeof(nfc_connstring), "%s:%s:%"PRIu32, PN532_SPI_DRIVER_NAME, acPort, PN532_SPI_DEFAULT_SPEED);
110 nfc_device *pnd = nfc_device_new(context, connstring);
111 if (!pnd) {
112 perror("malloc");
113 spi_close(sp);
114 iDevice = 0;
115 while ((acPort = acPorts[iDevice++])) {
116 free((void *)acPort);
117 }
118 free(acPorts);
119 return 0;
120 }
121 pnd->driver = &pn532_spi_driver;
122 pnd->driver_data = malloc(sizeof(struct pn532_spi_data));
123 if (!pnd->driver_data) {
124 perror("malloc");
125 spi_close(sp);
126 nfc_device_free(pnd);
127 iDevice = 0;
128 while ((acPort = acPorts[iDevice++])) {
129 free((void *)acPort);
130 }
131 free(acPorts);
132 return 0;
133 }
134 DRIVER_DATA(pnd)->port = sp;
135
136 // Alloc and init chip's data
137 if (pn53x_data_new(pnd, &pn532_spi_io) == NULL) {
138 perror("malloc");
139 spi_close(DRIVER_DATA(pnd)->port);
140 nfc_device_free(pnd);
141 iDevice = 0;
142 while ((acPort = acPorts[iDevice++])) {
143 free((void *)acPort);
144 }
145 free(acPorts);
146 return 0;
147 }
148 // SAMConfiguration command if needed to wakeup the chip and pn53x_SAMConfiguration check if the chip is a PN532
149 CHIP_DATA(pnd)->type = PN532;
150 // This device starts in LowVBat power mode
151 CHIP_DATA(pnd)->power_mode = LOWVBAT;
152
153 DRIVER_DATA(pnd)->abort_flag = false;
154
155 // Check communication using "Diagnose" command, with "Communication test" (0x00)
156 int res = pn53x_check_communication(pnd);
157 spi_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_spi_descriptor {
181 char *port;
182 uint32_t speed;
183 };
184
185 static void
pn532_spi_close(nfc_device * pnd)186 pn532_spi_close(nfc_device *pnd)
187 {
188 pn53x_idle(pnd);
189
190 // Release SPI port
191 spi_close(DRIVER_DATA(pnd)->port);
192
193 pn53x_data_free(pnd);
194 nfc_device_free(pnd);
195 }
196
197 static nfc_device *
pn532_spi_open(const nfc_context * context,const nfc_connstring connstring)198 pn532_spi_open(const nfc_context *context, const nfc_connstring connstring)
199 {
200 struct pn532_spi_descriptor ndd;
201 char *speed_s;
202 int connstring_decode_level = connstring_decode(connstring, PN532_SPI_DRIVER_NAME, NULL, &ndd.port, &speed_s);
203 if (connstring_decode_level == 3) {
204 ndd.speed = 0;
205 if (sscanf(speed_s, "%10"PRIu32, &ndd.speed) != 1) {
206 // speed_s is not a number
207 free(ndd.port);
208 free(speed_s);
209 return NULL;
210 }
211 free(speed_s);
212 }
213 if (connstring_decode_level < 2) {
214 return NULL;
215 }
216 if (connstring_decode_level < 3) {
217 ndd.speed = PN532_SPI_DEFAULT_SPEED;
218 }
219 spi_port sp;
220 nfc_device *pnd = NULL;
221
222 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Attempt to open: %s at %d Hz.", ndd.port, ndd.speed);
223 sp = spi_open(ndd.port);
224
225 if (sp == INVALID_SPI_PORT)
226 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Invalid SPI port: %s", ndd.port);
227 if (sp == CLAIMED_SPI_PORT)
228 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "SPI port already claimed: %s", ndd.port);
229 if ((sp == CLAIMED_SPI_PORT) || (sp == INVALID_SPI_PORT)) {
230 free(ndd.port);
231 return NULL;
232 }
233 spi_set_speed(sp, ndd.speed);
234 spi_set_mode(sp, PN532_SPI_MODE);
235
236 // We have a connection
237 pnd = nfc_device_new(context, connstring);
238 if (!pnd) {
239 perror("malloc");
240 free(ndd.port);
241 spi_close(sp);
242 return NULL;
243 }
244 snprintf(pnd->name, sizeof(pnd->name), "%s:%s", PN532_SPI_DRIVER_NAME, ndd.port);
245 free(ndd.port);
246
247 pnd->driver_data = malloc(sizeof(struct pn532_spi_data));
248 if (!pnd->driver_data) {
249 perror("malloc");
250 spi_close(sp);
251 nfc_device_free(pnd);
252 return NULL;
253 }
254 DRIVER_DATA(pnd)->port = sp;
255
256 // Alloc and init chip's data
257 if (pn53x_data_new(pnd, &pn532_spi_io) == NULL) {
258 perror("malloc");
259 spi_close(DRIVER_DATA(pnd)->port);
260 nfc_device_free(pnd);
261 return NULL;
262 }
263 // SAMConfiguration command if needed to wakeup the chip and pn53x_SAMConfiguration check if the chip is a PN532
264 CHIP_DATA(pnd)->type = PN532;
265 // This device starts in LowVBat mode
266 CHIP_DATA(pnd)->power_mode = LOWVBAT;
267
268 // empirical tuning
269 CHIP_DATA(pnd)->timer_correction = 48;
270 pnd->driver = &pn532_spi_driver;
271
272 DRIVER_DATA(pnd)->abort_flag = false;
273
274 // Check communication using "Diagnose" command, with "Communication test" (0x00)
275 if (pn53x_check_communication(pnd) < 0) {
276 nfc_perror(pnd, "pn53x_check_communication");
277 pn532_spi_close(pnd);
278 return NULL;
279 }
280
281 pn53x_init(pnd);
282 return pnd;
283 }
284
285 static int
pn532_spi_read_spi_status(nfc_device * pnd)286 pn532_spi_read_spi_status(nfc_device *pnd)
287 {
288 static const uint8_t pn532_spi_statread_cmd = 0x02;
289
290 uint8_t spi_status = 0;
291 int res = spi_send_receive(DRIVER_DATA(pnd)->port, &pn532_spi_statread_cmd, 1, &spi_status, 1, true);
292
293
294 if (res != NFC_SUCCESS) {
295 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Unable to read SPI status");
296 return res;
297 }
298
299 return spi_status;
300 }
301
302 int
pn532_spi_wakeup(nfc_device * pnd)303 pn532_spi_wakeup(nfc_device *pnd)
304 {
305 /* SPI wakeup is basically activating chipselect for several ms.
306 * To do so, we are sending harmless command at very low speed */
307
308 int res;
309 const uint32_t prev_port_speed = spi_get_speed(DRIVER_DATA(pnd)->port);
310
311
312
313
314 // Try to get byte from the SPI line. If PN532 is powered down, the byte will be 0xff (MISO line is high)
315 uint8_t spi_byte = 0;
316 res = spi_receive(DRIVER_DATA(pnd)->port, &spi_byte, 1, true);
317 if (res != NFC_SUCCESS) {
318 return res;
319 }
320
321 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Got %x byte from SPI line before wakeup", spi_byte);
322
323 CHIP_DATA(pnd)->power_mode = NORMAL; // PN532 will be awake soon
324 msleep(1);
325
326 if (spi_byte == 0xff) {
327 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Wakeup is needed");
328 spi_set_speed(DRIVER_DATA(pnd)->port, 5000); // set slow speed
329
330 res = pn532_SAMConfiguration(pnd, PSM_NORMAL, 1000); // wakeup by sending SAMConfiguration, which works just fine
331
332 spi_set_speed(DRIVER_DATA(pnd)->port, prev_port_speed);
333 }
334
335
336 return res;
337 }
338
339 #define PN532_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
340
341
342 static int
pn532_spi_wait_for_data(nfc_device * pnd,int timeout)343 pn532_spi_wait_for_data(nfc_device *pnd, int timeout)
344 {
345 static const uint8_t pn532_spi_ready = 0x01;
346 static const int pn532_spi_poll_interval = 10; //ms
347
348
349 int timer = 0;
350
351 int ret;
352 while ((ret = pn532_spi_read_spi_status(pnd)) != pn532_spi_ready) {
353 if (ret < 0) {
354 return ret;
355 }
356
357 if (DRIVER_DATA(pnd)->abort_flag) {
358 DRIVER_DATA(pnd)->abort_flag = false;
359 return NFC_EOPABORTED;
360 }
361
362 if (timeout > 0) {
363 timer += pn532_spi_poll_interval;
364 if (timer > timeout) {
365 return NFC_ETIMEOUT;
366 }
367
368 msleep(pn532_spi_poll_interval);
369 }
370 }
371
372 return NFC_SUCCESS;
373 }
374
375
376 static int
pn532_spi_receive_next_chunk(nfc_device * pnd,uint8_t * pbtData,const size_t szDataLen)377 pn532_spi_receive_next_chunk(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen)
378 {
379 // According to datasheet, the entire read operation should be done at once
380 // However, it seems impossible to do since the length of the frame is stored in the frame
381 // itself and it's impossible to manually set CS to low between two read operations
382
383 // It's possible to read the response frame in a series of read operations, provided
384 // each read operation is preceded by SPI_DATAREAD byte from the host.
385
386 // Unfortunately, the PN532 sends first byte of the second and successive response chunks
387 // at the same time as host sends SPI_DATAREAD byte
388
389 // Many hardware SPI implementations are half-duplex, so it's became impossible to read this
390 // first response byte
391
392 // The following hack is used here: we first try to receive data from PN532 without SPI_DATAREAD
393 // and then begin full-featured read operation
394
395 // The PN532 does not shift the internal register on the receive operation, which allows us to read the whole response
396
397 // The example transfer log is as follows:
398 // CS ..._/---\___________________________/---\________/------\_____________/-----\_________/---\____________/---...
399 // MOSI (host=>pn532) ... 0x03 0x00 0x00 0x00 0x00 0x00 0x03 0x00 0x00 0x03 0x00
400 // MISO (pn532<=host) ... 0x01 0x00 0xff 0x02 0xfe 0xd5 0xd5 0x15 0x16 0x16 0x00
401 // linux send/receive s r r r r r s r r s r
402 // |<-- data -->| |<-data->| |<-data->| |<-data->| |<-data->|
403 // |<-- first chunk -->| |<-- second chunk -->| |<-- third chunk -->|
404
405 // The response frame is 0x00 0xff 0x02 0xfe 0xd5 0x15 0x16 0x00
406
407
408 int res = spi_receive(DRIVER_DATA(pnd)->port, pbtData, 1, true);
409
410 if (res != NFC_SUCCESS) {
411 return res;
412 }
413
414 res = spi_send_receive(DRIVER_DATA(pnd)->port, &pn532_spi_cmd_dataread, 1, pbtData + 1, szDataLen - 1, true);
415
416 return res;
417 }
418
419 static int
pn532_spi_receive(nfc_device * pnd,uint8_t * pbtData,const size_t szDataLen,int timeout)420 pn532_spi_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int timeout)
421 {
422 uint8_t abtRxBuf[5];
423 size_t len;
424
425 pnd->last_error = pn532_spi_wait_for_data(pnd, timeout);
426
427 if (NFC_EOPABORTED == pnd->last_error) {
428 return pn532_spi_ack(pnd);
429 }
430
431 if (pnd->last_error != NFC_SUCCESS) {
432 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to wait for SPI data. (RX)");
433 goto error;
434 }
435
436 pnd->last_error = spi_send_receive(DRIVER_DATA(pnd)->port, &pn532_spi_cmd_dataread, 1, abtRxBuf , 4, true);
437
438 if (pnd->last_error < 0) {
439 goto error;
440 }
441
442 const uint8_t pn53x_long_preamble[3] = { 0x00, 0x00, 0xff };
443 if (0 == (memcmp(abtRxBuf, pn53x_long_preamble, 3))) {
444 // long preamble
445
446 // omit first byte
447 for (size_t i = 0; i < 3; ++i) {
448 abtRxBuf[i] = abtRxBuf[i + 1];
449 }
450
451 // need one more byte
452 pnd->last_error = pn532_spi_receive_next_chunk(pnd, abtRxBuf + 3, 1);
453 if (pnd->last_error != 0) {
454 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive one more byte for long preamble frame. (RX)");
455 goto error;
456 }
457 }
458
459
460 const uint8_t pn53x_preamble[2] = { 0x00, 0xff };
461 if (0 != (memcmp(abtRxBuf, pn53x_preamble, 2))) {
462 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", " preamble+start code mismatch");
463 pnd->last_error = NFC_EIO;
464 goto error;
465 }
466
467 if ((0x01 == abtRxBuf[2]) && (0xff == abtRxBuf[3])) {
468 // Error frame
469 pn532_spi_receive_next_chunk(pnd, abtRxBuf, 3);
470
471 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Application level error detected");
472 pnd->last_error = NFC_EIO;
473 goto error;
474 } else if ((0xff == abtRxBuf[2]) && (0xff == abtRxBuf[3])) {
475 // Extended frame
476 pnd->last_error = pn532_spi_receive_next_chunk(pnd, abtRxBuf, 3);
477
478 if (pnd->last_error != 0) {
479 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
480 goto error;
481 }
482 // (abtRxBuf[0] << 8) + abtRxBuf[1] (LEN) include TFI + (CC+1)
483 len = (abtRxBuf[0] << 8) + abtRxBuf[1] - 2;
484 if (((abtRxBuf[0] + abtRxBuf[1] + abtRxBuf[2]) % 256) != 0) {
485 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
486 pnd->last_error = NFC_EIO;
487 goto error;
488 }
489 } else {
490 // Normal frame
491 if (256 != (abtRxBuf[2] + abtRxBuf[3])) {
492 // TODO: Retry
493 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
494 pnd->last_error = NFC_EIO;
495 goto error;
496 }
497
498 // abtRxBuf[3] (LEN) include TFI + (CC+1)
499 len = abtRxBuf[2] - 2;
500 }
501
502 if (len > szDataLen) {
503 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to receive data: buffer too small. (szDataLen: %zu, len: %zu)", szDataLen, len);
504 pnd->last_error = NFC_EIO;
505 goto error;
506 }
507
508 // TFI + PD0 (CC+1)
509
510 pnd->last_error = pn532_spi_receive_next_chunk(pnd, abtRxBuf, 2);
511
512 if (pnd->last_error != 0) {
513 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
514 goto error;
515 }
516
517 if (abtRxBuf[0] != 0xD5) {
518 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "TFI Mismatch");
519 pnd->last_error = NFC_EIO;
520 goto error;
521 }
522
523 if (abtRxBuf[1] != CHIP_DATA(pnd)->last_command + 1) {
524 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Command Code verification failed");
525 pnd->last_error = NFC_EIO;
526 goto error;
527 }
528
529 if (len) {
530 pnd->last_error = pn532_spi_receive_next_chunk(pnd, pbtData, len);
531
532 if (pnd->last_error != 0) {
533 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
534 goto error;
535 }
536 }
537
538 pnd->last_error = pn532_spi_receive_next_chunk(pnd, abtRxBuf, 2);
539
540 if (pnd->last_error != 0) {
541 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to receive data. (RX)");
542 goto error;
543 }
544
545 uint8_t btDCS = (256 - 0xD5);
546 btDCS -= CHIP_DATA(pnd)->last_command + 1;
547 for (size_t szPos = 0; szPos < len; szPos++) {
548 btDCS -= pbtData[szPos];
549 }
550
551 if (btDCS != abtRxBuf[0]) {
552 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Data checksum mismatch");
553 pnd->last_error = NFC_EIO;
554 goto error;
555 }
556
557 if (0x00 != abtRxBuf[1]) {
558 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame postamble mismatch");
559 pnd->last_error = NFC_EIO;
560 goto error;
561 }
562 // The PN53x command is done and we successfully received the reply
563 return len;
564 error:
565 return pnd->last_error;
566 }
567
568 static int
pn532_spi_send(nfc_device * pnd,const uint8_t * pbtData,const size_t szData,int timeout)569 pn532_spi_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout)
570 {
571 int res = 0;
572
573 switch (CHIP_DATA(pnd)->power_mode) {
574 case LOWVBAT: {
575 /** PN532C106 wakeup. */
576 if ((res = pn532_spi_wakeup(pnd)) < 0) {
577 return res;
578 }
579 // 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
580 if ((res = pn532_SAMConfiguration(pnd, PSM_NORMAL, 1000)) < 0) {
581 return res;
582 }
583 }
584 break;
585 case POWERDOWN: {
586 if ((res = pn532_spi_wakeup(pnd)) < 0) {
587 return res;
588 }
589 }
590 break;
591 case NORMAL:
592 // Nothing to do :)
593 break;
594 };
595
596 uint8_t abtFrame[PN532_BUFFER_LEN + 1] = { pn532_spi_cmd_datawrite, 0x00, 0x00, 0xff }; // SPI data transfer starts with DATAWRITE (0x01) byte, Every packet must start with "00 00 ff"
597 size_t szFrame = 0;
598
599 if ((res = pn53x_build_frame(abtFrame + 1, &szFrame, pbtData, szData)) < 0) {
600 pnd->last_error = res;
601 return pnd->last_error;
602 }
603
604 res = spi_send(DRIVER_DATA(pnd)->port, abtFrame, szFrame, true);
605 if (res != 0) {
606 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
607 pnd->last_error = res;
608 return pnd->last_error;
609 }
610
611 res = pn532_spi_wait_for_data(pnd, timeout);
612 if (res != NFC_SUCCESS) {
613 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to wait for SPI data. (RX)");
614 pnd->last_error = res;
615 return pnd->last_error;
616 }
617
618
619
620 uint8_t abtRxBuf[PN53x_ACK_FRAME__LEN];
621 res = spi_send_receive(DRIVER_DATA(pnd)->port, &pn532_spi_cmd_dataread, 1, abtRxBuf, sizeof(abtRxBuf), true);
622
623 if (res != 0) {
624 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Unable to read ACK");
625 pnd->last_error = res;
626 return pnd->last_error;
627 }
628
629 if (pn53x_check_ack_frame(pnd, abtRxBuf, sizeof(abtRxBuf)) == 0) {
630 // The PN53x is running the sent command
631 } else {
632 return pnd->last_error;
633 }
634 return NFC_SUCCESS;
635 }
636
637
638 int
pn532_spi_ack(nfc_device * pnd)639 pn532_spi_ack(nfc_device *pnd)
640 {
641 const size_t ack_frame_len = (sizeof(pn53x_ack_frame) / sizeof(pn53x_ack_frame[0]));
642 uint8_t ack_tx_buf [1 + ack_frame_len];
643
644 ack_tx_buf[0] = pn532_spi_cmd_datawrite;
645 memcpy(ack_tx_buf + 1, pn53x_ack_frame, ack_frame_len);
646
647
648 int res = spi_send(DRIVER_DATA(pnd)->port, ack_tx_buf, ack_frame_len + 1, true);
649 return res;
650 }
651
652 static int
pn532_spi_abort_command(nfc_device * pnd)653 pn532_spi_abort_command(nfc_device *pnd)
654 {
655 if (pnd) {
656 DRIVER_DATA(pnd)->abort_flag = true;
657 }
658
659 return NFC_SUCCESS;
660 }
661
662 const struct pn53x_io pn532_spi_io = {
663 .send = pn532_spi_send,
664 .receive = pn532_spi_receive,
665 };
666
667 const struct nfc_driver pn532_spi_driver = {
668 .name = PN532_SPI_DRIVER_NAME,
669 .scan_type = INTRUSIVE,
670 .scan = pn532_spi_scan,
671 .open = pn532_spi_open,
672 .close = pn532_spi_close,
673 .strerror = pn53x_strerror,
674
675 .initiator_init = pn53x_initiator_init,
676 .initiator_init_secure_element = pn532_initiator_init_secure_element,
677 .initiator_select_passive_target = pn53x_initiator_select_passive_target,
678 .initiator_poll_target = pn53x_initiator_poll_target,
679 .initiator_select_dep_target = pn53x_initiator_select_dep_target,
680 .initiator_deselect_target = pn53x_initiator_deselect_target,
681 .initiator_transceive_bytes = pn53x_initiator_transceive_bytes,
682 .initiator_transceive_bits = pn53x_initiator_transceive_bits,
683 .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed,
684 .initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed,
685 .initiator_target_is_present = pn53x_initiator_target_is_present,
686
687 .target_init = pn53x_target_init,
688 .target_send_bytes = pn53x_target_send_bytes,
689 .target_receive_bytes = pn53x_target_receive_bytes,
690 .target_send_bits = pn53x_target_send_bits,
691 .target_receive_bits = pn53x_target_receive_bits,
692
693 .device_set_property_bool = pn53x_set_property_bool,
694 .device_set_property_int = pn53x_set_property_int,
695 .get_supported_modulation = pn53x_get_supported_modulation,
696 .get_supported_baud_rate = pn53x_get_supported_baud_rate,
697 .device_get_information_about = pn53x_get_information_about,
698
699 .abort_command = pn532_spi_abort_command,
700 .idle = pn53x_idle,
701 .powerdown = pn53x_PowerDown,
702 };
703
704