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 Laurent Latil
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_i2c.c
30 * @brief PN532 driver using I2C bus.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif // HAVE_CONFIG_H
36
37 #include "pn532_i2c.h"
38
39 #include <stdio.h>
40 #include <inttypes.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <time.h>
45
46 #include <nfc/nfc.h>
47
48 #include "drivers.h"
49 #include "nfc-internal.h"
50 #include "chips/pn53x.h"
51 #include "chips/pn53x-internal.h"
52 #include "buses/i2c.h"
53
54 #define PN532_I2C_DRIVER_NAME "pn532_i2c"
55
56 #define LOG_CATEGORY "libnfc.driver.pn532_i2c"
57 #define LOG_GROUP NFC_LOG_GROUP_DRIVER
58
59 // I2C address of the PN532 chip.
60 #define PN532_I2C_ADDR 0x24
61
62 // Internal data structs
63 const struct pn53x_io pn532_i2c_io;
64
65 struct pn532_i2c_data {
66 i2c_device dev;
67 volatile bool abort_flag;
68 };
69
70 /* Delay for the loop waiting for READY frame (in ms) */
71 #define PN532_RDY_LOOP_DELAY 90
72
73 const struct timespec rdyDelay = {
74 .tv_sec = 0,
75 .tv_nsec = PN532_RDY_LOOP_DELAY * 1000 * 1000
76 };
77
78 /* Private Functions Prototypes */
79
80 static nfc_device *pn532_i2c_open(const nfc_context *context, const nfc_connstring connstring);
81
82 static void pn532_i2c_close(nfc_device *pnd);
83
84 static int pn532_i2c_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout);
85
86 static int pn532_i2c_ack(nfc_device *pnd);
87
88 static int pn532_i2c_abort_command(nfc_device *pnd);
89
90 static int pn532_i2c_wakeup(nfc_device *pnd);
91
92 static int pn532_i2c_wait_rdyframe(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int timeout);
93
94 static size_t pn532_i2c_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len);
95
96
97 #define DRIVER_DATA(pnd) ((struct pn532_i2c_data*)(pnd->driver_data))
98
99 /**
100 * @brief Scan all available I2C buses to find PN532 devices.
101 *
102 * @param context NFC context.
103 * @param connstrings array of 'nfc_connstring' buffer (allocated by caller). It is used to store the
104 * connection info strings of all I2C PN532 devices found.
105 * @param connstrings_len length of the connstrings array.
106 * @return number of PN532 devices found on all I2C buses.
107 */
108 static size_t
pn532_i2c_scan(const nfc_context * context,nfc_connstring connstrings[],const size_t connstrings_len)109 pn532_i2c_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
110 {
111 size_t device_found = 0;
112 i2c_device id;
113 char **i2cPorts = i2c_list_ports();
114 const char *i2cPort;
115 int iDevice = 0;
116
117 while ((i2cPort = i2cPorts[iDevice++])) {
118 id = i2c_open(i2cPort, PN532_I2C_ADDR);
119 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Trying to find PN532 device on I2C bus %s.", i2cPort);
120
121 if ((id != INVALID_I2C_ADDRESS) && (id != INVALID_I2C_BUS)) {
122 nfc_connstring connstring;
123 snprintf(connstring, sizeof(nfc_connstring), "%s:%s", PN532_I2C_DRIVER_NAME, i2cPort);
124 nfc_device *pnd = nfc_device_new(context, connstring);
125 if (!pnd) {
126 perror("malloc");
127 i2c_close(id);
128 iDevice = 0;
129 while ((i2cPort = i2cPorts[iDevice++])) {
130 free((void *)i2cPort);
131 }
132 free(i2cPorts);
133 return 0;
134 }
135 pnd->driver = &pn532_i2c_driver;
136 pnd->driver_data = malloc(sizeof(struct pn532_i2c_data));
137 if (!pnd->driver_data) {
138 perror("malloc");
139 i2c_close(id);
140 nfc_device_free(pnd);
141 iDevice = 0;
142 while ((i2cPort = i2cPorts[iDevice++])) {
143 free((void *)i2cPort);
144 }
145 free(i2cPorts);
146 return 0;
147 }
148 DRIVER_DATA(pnd)->dev = id;
149
150 // Alloc and init chip's data
151 if (pn53x_data_new(pnd, &pn532_i2c_io) == NULL) {
152 perror("malloc");
153 i2c_close(DRIVER_DATA(pnd)->dev);
154 nfc_device_free(pnd);
155 iDevice = 0;
156 while ((i2cPort = i2cPorts[iDevice++])) {
157 free((void *)i2cPort);
158 }
159 free(i2cPorts);
160 return 0;
161 }
162
163 // SAMConfiguration command if needed to wakeup the chip and pn53x_SAMConfiguration check if the chip is a PN532
164 CHIP_DATA(pnd)->type = PN532;
165 // This device starts in LowVBat power mode
166 CHIP_DATA(pnd)->power_mode = LOWVBAT;
167
168 DRIVER_DATA(pnd)->abort_flag = false;
169
170 // Check communication using "Diagnose" command, with "Communication test" (0x00)
171 int res = pn53x_check_communication(pnd);
172 i2c_close(DRIVER_DATA(pnd)->dev);
173 pn53x_data_free(pnd);
174 nfc_device_free(pnd);
175 if (res < 0) {
176 continue;
177 }
178
179 memcpy(connstrings[device_found], connstring, sizeof(nfc_connstring));
180 device_found++;
181
182 // Test if we reach the maximum "wanted" devices
183 if (device_found >= connstrings_len)
184 break;
185 }
186 }
187 iDevice = 0;
188 while ((i2cPort = i2cPorts[iDevice++])) {
189 free((void *)i2cPort);
190 }
191 free(i2cPorts);
192 return device_found;
193 }
194
195 /**
196 * @brief Close I2C connection to the PN532 device.
197 *
198 * @param pnd pointer on the device to close.
199 */
200 static void
pn532_i2c_close(nfc_device * pnd)201 pn532_i2c_close(nfc_device *pnd)
202 {
203 pn53x_idle(pnd);
204 i2c_close(DRIVER_DATA(pnd)->dev);
205
206 pn53x_data_free(pnd);
207 nfc_device_free(pnd);
208 }
209
210 /**
211 * @brief Open an I2C connection to the PN532 device.
212 *
213 * @param context NFC context.
214 * @param connstring connection info to the device ( pn532_i2c:<i2c_devname> ).
215 * @return pointer to the device, or NULL in case of error.
216 */
217 static nfc_device *
pn532_i2c_open(const nfc_context * context,const nfc_connstring connstring)218 pn532_i2c_open(const nfc_context *context, const nfc_connstring connstring)
219 {
220 char *i2c_devname;
221 i2c_device i2c_dev;
222 nfc_device *pnd;
223
224 int connstring_decode_level = connstring_decode(connstring, PN532_I2C_DRIVER_NAME, NULL, &i2c_devname, NULL);
225
226 switch (connstring_decode_level) {
227 case 2:
228 break;
229 case 1:
230 break;
231 case 0:
232 return NULL;
233 }
234
235 i2c_dev = i2c_open(i2c_devname, PN532_I2C_ADDR);
236
237 if (i2c_dev == INVALID_I2C_BUS || i2c_dev == INVALID_I2C_ADDRESS) {
238 return NULL;
239 }
240
241 pnd = nfc_device_new(context, connstring);
242 if (!pnd) {
243 perror("malloc");
244 i2c_close(i2c_dev);
245 return NULL;
246 }
247 snprintf(pnd->name, sizeof(pnd->name), "%s:%s", PN532_I2C_DRIVER_NAME, i2c_devname);
248
249 pnd->driver_data = malloc(sizeof(struct pn532_i2c_data));
250 if (!pnd->driver_data) {
251 perror("malloc");
252 i2c_close(i2c_dev);
253 nfc_device_free(pnd);
254 return NULL;
255 }
256 DRIVER_DATA(pnd)->dev = i2c_dev;
257
258 // Alloc and init chip's data
259 if (pn53x_data_new(pnd, &pn532_i2c_io) == NULL) {
260 perror("malloc");
261 i2c_close(i2c_dev);
262 nfc_device_free(pnd);
263 return NULL;
264 }
265
266 // SAMConfiguration command if needed to wakeup the chip and pn53x_SAMConfiguration check if the chip is a PN532
267 CHIP_DATA(pnd)->type = PN532;
268 // This device starts in LowVBat mode
269 CHIP_DATA(pnd)->power_mode = LOWVBAT;
270
271 // empirical tuning
272 CHIP_DATA(pnd)->timer_correction = 48;
273 pnd->driver = &pn532_i2c_driver;
274
275 DRIVER_DATA(pnd)->abort_flag = false;
276
277 // Check communication using "Diagnose" command, with "Communication test" (0x00)
278 if (pn53x_check_communication(pnd) < 0) {
279 nfc_perror(pnd, "pn53x_check_communication");
280 pn532_i2c_close(pnd);
281 return NULL;
282 }
283
284 pn53x_init(pnd);
285 return pnd;
286 }
287
288 static int
pn532_i2c_wakeup(nfc_device * pnd)289 pn532_i2c_wakeup(nfc_device *pnd)
290 {
291 /* No specific. PN532 holds SCL during wakeup time */
292 CHIP_DATA(pnd)->power_mode = NORMAL; // PN532 should now be awake
293 return NFC_SUCCESS;
294 }
295
296 #define PN532_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
297
298 /**
299 * @brief Send data to the PN532 device.
300 *
301 * @param pnd pointer on the NFC device.
302 * @param pbtData buffer containing frame data.
303 * @param szData size of the buffer.
304 * @param timeout timeout before aborting the operation (in ms).
305 * @return NFC_SUCCESS if operation is successful, or error code.
306 */
307 static int
pn532_i2c_send(nfc_device * pnd,const uint8_t * pbtData,const size_t szData,int timeout)308 pn532_i2c_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout)
309 {
310 int res = 0;
311
312 // Discard any existing data ?
313
314 switch (CHIP_DATA(pnd)->power_mode) {
315 case LOWVBAT: {
316 /** PN532C106 wakeup. */
317 if ((res = pn532_i2c_wakeup(pnd)) < 0) {
318 return res;
319 }
320 // 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
321 if ((res = pn532_SAMConfiguration(pnd, PSM_NORMAL, 1000)) < 0) {
322 return res;
323 }
324 }
325 break;
326 case POWERDOWN: {
327 if ((res = pn532_i2c_wakeup(pnd)) < 0) {
328 return res;
329 }
330 }
331 break;
332 case NORMAL:
333 // Nothing to do :)
334 break;
335 };
336
337 uint8_t abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
338 size_t szFrame = 0;
339
340 if ((res = pn53x_build_frame(abtFrame, &szFrame, pbtData, szData)) < 0) {
341 pnd->last_error = res;
342 return pnd->last_error;
343 }
344
345 res = i2c_write(DRIVER_DATA(pnd)->dev, abtFrame, szFrame);
346
347 if (res < 0) {
348 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
349 pnd->last_error = res;
350 return pnd->last_error;
351 }
352
353 uint8_t abtRxBuf[PN53x_ACK_FRAME__LEN];
354
355 // Wait for the ACK frame
356 res = pn532_i2c_wait_rdyframe(pnd, abtRxBuf, sizeof(abtRxBuf), timeout);
357 if (res < 0) {
358 if (res == NFC_EOPABORTED) {
359 // Send an ACK frame from host to abort the command.
360 pn532_i2c_ack(pnd);
361 }
362 pnd->last_error = res;
363 return pnd->last_error;
364 }
365
366 if (pn53x_check_ack_frame(pnd, abtRxBuf, res) == 0) {
367 // The PN53x is running the sent command
368 } else {
369 return pnd->last_error;
370 }
371 return NFC_SUCCESS;
372 }
373
374 /**
375 * @brief Read data from the PN532 device until getting a frame with RDY bit set
376 *
377 * @param pnd pointer on the NFC device.
378 * @param pbtData buffer used to store the received frame data.
379 * @param szDataLen allocated size of buffer.
380 * @param timeout timeout delay before aborting the operation (in ms). Use 0 for no timeout.
381 * @return length (in bytes) of the received frame, or NFC_ETIMEOUT if timeout delay has expired,
382 * NFC_EOPABORTED if operation has been aborted, NFC_EIO in case of IO failure
383 */
384 static int
pn532_i2c_wait_rdyframe(nfc_device * pnd,uint8_t * pbtData,const size_t szDataLen,int timeout)385 pn532_i2c_wait_rdyframe(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int timeout)
386 {
387 bool done = false;
388 int res;
389
390 struct timeval start_tv, cur_tv;
391 long long duration;
392
393 // Actual I2C response frame includes an additional status byte,
394 // so we use a temporary buffer to read the I2C frame
395 uint8_t i2cRx[PN53x_EXTENDED_FRAME__DATA_MAX_LEN + 1];
396
397 if (timeout > 0) {
398 // If a timeout is specified, get current timestamp
399 gettimeofday(&start_tv, NULL);
400 }
401
402 do {
403 // Wait a little bit before reading
404 nanosleep(&rdyDelay, (struct timespec *) NULL);
405
406 int recCount = i2c_read(DRIVER_DATA(pnd)->dev, i2cRx, szDataLen + 1);
407
408 if (DRIVER_DATA(pnd)->abort_flag) {
409 // Reset abort flag
410 DRIVER_DATA(pnd)->abort_flag = false;
411
412 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG,
413 "Wait for a READY frame has been aborted.");
414 return NFC_EOPABORTED;
415 }
416
417 if (recCount <= 0) {
418 done = true;
419 res = NFC_EIO;
420 } else {
421 const uint8_t rdy = i2cRx[0];
422 if (rdy & 1) {
423 int copyLength;
424
425 done = true;
426 res = recCount - 1;
427 copyLength = MIN(res, (int)szDataLen);
428 memcpy(pbtData, &(i2cRx[1]), copyLength);
429 } else {
430 /* Not ready yet. Check for elapsed timeout. */
431
432 if (timeout > 0) {
433 gettimeofday(&cur_tv, NULL);
434 duration = (cur_tv.tv_sec - start_tv.tv_sec) * 1000000L
435 + (cur_tv.tv_usec - start_tv.tv_usec);
436
437 if (duration / 1000 > timeout) {
438 res = NFC_ETIMEOUT;
439 done = true;
440
441 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG,
442 "timeout reached with no READY frame.");
443 }
444 }
445 }
446 }
447 } while (!done);
448
449 return res;
450 }
451
452 /**
453 * @brief Read a response frame from the PN532 device.
454 *
455 * @param pnd pointer on the NFC device.
456 * @param pbtData buffer used to store the response frame data.
457 * @param szDataLen allocated size of buffer.
458 * @param timeout timeout delay before aborting the operation (in ms). Use 0 for no timeout.
459 * @return length (in bytes) of the response, or NFC_ETIMEOUT if timeout delay has expired,
460 * NFC_EOPABORTED if operation has been aborted, NFC_EIO in case of IO failure
461 */
462 static int
pn532_i2c_receive(nfc_device * pnd,uint8_t * pbtData,const size_t szDataLen,int timeout)463 pn532_i2c_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, int timeout)
464 {
465 uint8_t frameBuf[PN53x_EXTENDED_FRAME__DATA_MAX_LEN];
466 int frameLength;
467 int TFI_idx;
468 size_t len;
469
470 frameLength = pn532_i2c_wait_rdyframe(pnd, frameBuf, sizeof(frameBuf), timeout);
471
472 if (NFC_EOPABORTED == pnd->last_error) {
473 return pn532_i2c_ack(pnd);
474 }
475
476 if (frameLength < 0) {
477 goto error;
478 }
479
480 const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
481
482 if (0 != (memcmp(frameBuf, pn53x_preamble, 3))) {
483 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
484 pnd->last_error = NFC_EIO;
485 goto error;
486 }
487
488 if ((0x01 == frameBuf[3]) && (0xff == frameBuf[4])) {
489 uint8_t errorCode = frameBuf[5];
490 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Application level error detected (%d)", errorCode);
491 pnd->last_error = NFC_EIO;
492 goto error;
493 } else if ((0xff == frameBuf[3]) && (0xff == frameBuf[4])) {
494 // Extended frame
495 len = (frameBuf[5] << 8) + frameBuf[6];
496
497 // Verify length checksum
498 if (((frameBuf[5] + frameBuf[6] + frameBuf[7]) % 256) != 0) {
499 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Length checksum mismatch");
500 pnd->last_error = NFC_EIO;
501 goto error;
502 }
503 TFI_idx = 8;
504 } else {
505 // Normal frame
506
507 len = frameBuf[3];
508
509 // Verify length checksum
510 if ((uint8_t)(frameBuf[3] + frameBuf[4])) {
511 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
512 pnd->last_error = NFC_EIO;
513 goto error;
514 }
515 TFI_idx = 5;
516 }
517
518 if ((len - 2) > szDataLen) {
519 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to receive data: buffer too small. (szDataLen: %" PRIuPTR ", len: %" PRIuPTR ")", szDataLen, len);
520 pnd->last_error = NFC_EIO;
521 goto error;
522 }
523
524 uint8_t TFI = frameBuf[TFI_idx];
525 if (TFI != 0xD5) {
526 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "TFI Mismatch");
527 pnd->last_error = NFC_EIO;
528 goto error;
529 }
530
531 if (frameBuf[TFI_idx + 1] != CHIP_DATA(pnd)->last_command + 1) {
532 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Command Code verification failed. (got %d, expected %d)",
533 frameBuf[TFI_idx + 1], CHIP_DATA(pnd)->last_command + 1);
534 pnd->last_error = NFC_EIO;
535 goto error;
536 }
537
538 uint8_t DCS = frameBuf[TFI_idx + len];
539 uint8_t btDCS = DCS;
540
541 // Compute data checksum
542 for (size_t i = 0; i < len; i++) {
543 btDCS += frameBuf[TFI_idx + i];
544 }
545
546 if (btDCS != 0) {
547 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Data checksum mismatch (DCS = %02x, btDCS = %d)", DCS, btDCS);
548 pnd->last_error = NFC_EIO;
549 goto error;
550 }
551
552 if (0x00 != frameBuf[TFI_idx + len + 1]) {
553 log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Frame postamble mismatch (got %d)", frameBuf[frameLength - 1]);
554 pnd->last_error = NFC_EIO;
555 goto error;
556 }
557
558 memcpy(pbtData, &frameBuf[TFI_idx + 2], len - 2);
559
560 /* The PN53x command is done and we successfully received the reply */
561 return len - 2;
562 error:
563 return pnd->last_error;
564 }
565
566 /**
567 * @brief Send an ACK frame to the PN532 device.
568 *
569 * @param pnd pointer on the NFC device.
570 * @return NFC_SUCCESS on success, otherwise an error code
571 */
572 int
pn532_i2c_ack(nfc_device * pnd)573 pn532_i2c_ack(nfc_device *pnd)
574 {
575 return i2c_write(DRIVER_DATA(pnd)->dev, pn53x_ack_frame, sizeof(pn53x_ack_frame));
576 }
577
578 /**
579 * @brief Abort any pending operation
580 *
581 * @param pnd pointer on the NFC device.
582 * @return NFC_SUCCESS
583 */
584 static int
pn532_i2c_abort_command(nfc_device * pnd)585 pn532_i2c_abort_command(nfc_device *pnd)
586 {
587 if (pnd) {
588 DRIVER_DATA(pnd)->abort_flag = true;
589 }
590 return NFC_SUCCESS;
591 }
592
593 const struct pn53x_io pn532_i2c_io = {
594 .send = pn532_i2c_send,
595 .receive = pn532_i2c_receive,
596 };
597
598 const struct nfc_driver pn532_i2c_driver = {
599 .name = PN532_I2C_DRIVER_NAME,
600 .scan_type = INTRUSIVE,
601 .scan = pn532_i2c_scan,
602 .open = pn532_i2c_open,
603 .close = pn532_i2c_close,
604 .strerror = pn53x_strerror,
605
606 .initiator_init = pn53x_initiator_init,
607 .initiator_init_secure_element = pn532_initiator_init_secure_element,
608 .initiator_select_passive_target = pn53x_initiator_select_passive_target,
609 .initiator_poll_target = pn53x_initiator_poll_target,
610 .initiator_select_dep_target = pn53x_initiator_select_dep_target,
611 .initiator_deselect_target = pn53x_initiator_deselect_target,
612 .initiator_transceive_bytes = pn53x_initiator_transceive_bytes,
613 .initiator_transceive_bits = pn53x_initiator_transceive_bits,
614 .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed,
615 .initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed,
616 .initiator_target_is_present = pn53x_initiator_target_is_present,
617
618 .target_init = pn53x_target_init,
619 .target_send_bytes = pn53x_target_send_bytes,
620 .target_receive_bytes = pn53x_target_receive_bytes,
621 .target_send_bits = pn53x_target_send_bits,
622 .target_receive_bits = pn53x_target_receive_bits,
623
624 .device_set_property_bool = pn53x_set_property_bool,
625 .device_set_property_int = pn53x_set_property_int,
626 .get_supported_modulation = pn53x_get_supported_modulation,
627 .get_supported_baud_rate = pn53x_get_supported_baud_rate,
628 .device_get_information_about = pn53x_get_information_about,
629
630 .abort_command = pn532_i2c_abort_command,
631 .idle = pn53x_idle,
632 .powerdown = pn53x_PowerDown,
633 };
634
635