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