libnfc  1.4.2
pn532_uart.c
Go to the documentation of this file.
1 /*-
2  * Public platform independent Near Field Communication (NFC) library
3  *
4  * Copyright (C) 2009, Roel Verdult
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>
18  */
19 
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif // HAVE_CONFIG_H
28 
29 #include "../drivers.h"
30 
31 #include <stdio.h>
32 #include <string.h>
33 
34 #include "pn532_uart.h"
35 
36 #include <nfc/nfc.h>
37 #include <nfc/nfc-messages.h>
38 
39 // Bus
40 #include "uart.h"
41 
42 #define SERIAL_DEFAULT_PORT_SPEED 115200
43 
44 // TODO Move this one level up for libnfc-1.6
45 static const byte_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
46 
47 void pn532_uart_ack (const nfc_device_spec_t nds);
48 void pn532_uart_wakeup (const nfc_device_spec_t nds);
49 bool pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success);
50 
52 pn532_uart_pick_device (void)
53 {
54  nfc_device_desc_t *pndd;
55 
56  if ((pndd = malloc (sizeof (*pndd)))) {
57  size_t szN;
58 
59  if (!pn532_uart_list_devices (pndd, 1, &szN)) {
60  DBG ("%s", "pn532_uart_list_devices failed");
61  free (pndd);
62  return NULL;
63  }
64 
65  if (szN == 0) {
66  DBG ("%s", "No device found");
67  free (pndd);
68  return NULL;
69  }
70  }
71 
72  return pndd;
73 }
74 
75 bool
76 pn532_uart_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound)
77 {
81 #ifndef SERIAL_AUTOPROBE_ENABLED
82  (void) pnddDevices;
83  (void) szDevices;
84  *pszDeviceFound = 0;
85  DBG ("%s", "Serial auto-probing have been disabled at compile time. Skipping autoprobe.");
86  return false;
87 #else /* SERIAL_AUTOPROBE_ENABLED */
88  *pszDeviceFound = 0;
89 
90  serial_port sp;
91  const char *pcPorts[] = DEFAULT_SERIAL_PORTS;
92  const char *pcPort;
93  int iDevice = 0;
94 
95  while ((pcPort = pcPorts[iDevice++])) {
96  sp = uart_open (pcPort);
97  DBG ("Trying to find PN532 device on serial port: %s at %d bauds.", pcPort, SERIAL_DEFAULT_PORT_SPEED);
98 
99  if ((sp != INVALID_SERIAL_PORT) && (sp != CLAIMED_SERIAL_PORT)) {
100  bool bComOk;
101  // Serial port claimed but we need to check if a PN532_UART is connected.
102  uart_set_speed (sp, SERIAL_DEFAULT_PORT_SPEED);
103  // PN532 could be powered down, we need to wake it up before line testing.
104  pn532_uart_wakeup ((nfc_device_spec_t) sp);
105  // Check communication using "Diagnose" command, with "Communication test" (0x00)
106  if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk))
107  continue;
108  if (!bComOk)
109  continue;
110  uart_close (sp);
111 
112  snprintf (pnddDevices[*pszDeviceFound].acDevice, DEVICE_NAME_LENGTH - 1, "%s (%s)", "PN532", pcPort);
113  pnddDevices[*pszDeviceFound].acDevice[DEVICE_NAME_LENGTH - 1] = '\0';
114  pnddDevices[*pszDeviceFound].pcDriver = PN532_UART_DRIVER_NAME;
115  pnddDevices[*pszDeviceFound].pcPort = strdup (pcPort);
116  pnddDevices[*pszDeviceFound].uiSpeed = SERIAL_DEFAULT_PORT_SPEED;
117  DBG ("Device found: %s.", pnddDevices[*pszDeviceFound].acDevice);
118  (*pszDeviceFound)++;
119 
120  // Test if we reach the maximum "wanted" devices
121  if ((*pszDeviceFound) >= szDevices)
122  break;
123  }
124 # ifdef DEBUG
125  if (sp == INVALID_SERIAL_PORT)
126  DBG ("Invalid serial port: %s", pcPort);
127  if (sp == CLAIMED_SERIAL_PORT)
128  DBG ("Serial port already claimed: %s", pcPort);
129 # endif
130  /* DEBUG */
131  }
132 #endif /* SERIAL_AUTOPROBE_ENABLED */
133  return true;
134 }
135 
136 nfc_device_t *
137 pn532_uart_connect (const nfc_device_desc_t * pndd)
138 {
139  serial_port sp;
140  nfc_device_t *pnd = NULL;
141  bool bComOk;
142 
143  DBG ("Attempt to connect to: %s at %d bauds.", pndd->pcPort, pndd->uiSpeed);
144  sp = uart_open (pndd->pcPort);
145 
146  if (sp == INVALID_SERIAL_PORT)
147  ERR ("Invalid serial port: %s", pndd->pcPort);
148  if (sp == CLAIMED_SERIAL_PORT)
149  ERR ("Serial port already claimed: %s", pndd->pcPort);
150  if ((sp == CLAIMED_SERIAL_PORT) || (sp == INVALID_SERIAL_PORT))
151  return NULL;
152 
153  uart_set_speed (sp, pndd->uiSpeed);
154 
155  // PN532 could be powered down, we need to wake it up before line testing.
156  pn532_uart_wakeup ((nfc_device_spec_t) sp);
157  // Check communication using "Diagnose" command, with "Communication test" (0x00)
158  if (!pn532_uart_check_communication ((nfc_device_spec_t) sp, &bComOk))
159  return NULL;
160  if (!bComOk)
161  return NULL;
162 
163  DBG ("Successfully connected to: %s", pndd->pcPort);
164 
165  // We have a connection
166  pnd = malloc (sizeof (nfc_device_t));
167  strncpy (pnd->acName, pndd->acDevice, DEVICE_NAME_LENGTH - 1);
168  pnd->acName[DEVICE_NAME_LENGTH - 1] = '\0';
169 
170  pnd->nc = NC_PN532;
171  pnd->nds = (nfc_device_spec_t) sp;
172  pnd->bActive = true;
173 
174  return pnd;
175 }
176 
177 void
178 pn532_uart_disconnect (nfc_device_t * pnd)
179 {
180  uart_close ((serial_port) pnd->nds);
181  free (pnd);
182 }
183 
184 #define TX_BUFFER_LEN (256)
185 #define RX_BUFFER_LEN (PN53x_EXTENDED_FRAME_MAX_LEN + PN53x_EXTENDED_FRAME_OVERHEAD)
186 bool
187 pn532_uart_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
188  size_t * pszRx)
189 {
190  byte_t abtTxBuf[TX_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
191  byte_t abtRxBuf[RX_BUFFER_LEN];
192  size_t szRxBufLen = MIN( RX_BUFFER_LEN, *pszRx );
193  size_t szPos;
194  int res;
195 
196  // Packet length = data length (len) + checksum (1) + end of stream marker (1)
197  abtTxBuf[3] = szTx;
198  // Packet length checksum
199  abtTxBuf[4] = 256 - abtTxBuf[3];
200  // Copy the PN53X command into the packet buffer
201  memmove (abtTxBuf + 5, pbtTx, szTx);
202 
203  // Calculate data payload checksum
204  abtTxBuf[szTx + 5] = 0;
205  for (szPos = 0; szPos < szTx; szPos++) {
206  abtTxBuf[szTx + 5] -= abtTxBuf[szPos + 5];
207  }
208 
209  // End of stream marker
210  abtTxBuf[szTx + 6] = 0;
211 
212 #ifdef DEBUG
213  PRINT_HEX ("TX", abtTxBuf, szTx + 7);
214 #endif
215  res = uart_send ((serial_port) pnd->nds, abtTxBuf, szTx + 7);
216  if (res != 0) {
217  ERR ("%s", "Unable to transmit data. (TX)");
218  pnd->iLastError = res;
219  return false;
220  }
221 
222  res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
223  if (res != 0) {
224  ERR ("%s", "Unable to receive data. (RX)");
225  pnd->iLastError = res;
226  return false;
227  }
228 #ifdef DEBUG
229  PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
230 #endif
231 
232  // WARN: UART is a per byte reception, so you usually receive ACK and next frame the same time
233  if (!pn53x_check_ack_frame_callback (pnd, abtRxBuf, szRxBufLen))
234  return false;
235  szRxBufLen -= sizeof (ack_frame);
236  memmove (abtRxBuf, abtRxBuf + sizeof (ack_frame), szRxBufLen);
237 
238  if (szRxBufLen == 0) {
239  szRxBufLen = RX_BUFFER_LEN;
240  do {
241  delay_ms (10);
242  res = uart_receive ((serial_port) pnd->nds, abtRxBuf, &szRxBufLen);
243  } while (res != 0);
244 #ifdef DEBUG
245  PRINT_HEX ("RX", abtRxBuf, szRxBufLen);
246 #endif
247  }
248 
249 #ifdef DEBUG
250  PRINT_HEX ("TX", ack_frame, sizeof(ack_frame));
251 #endif
252  res = uart_send ((serial_port) pnd->nds, ack_frame, sizeof(ack_frame));
253  if (res != 0) {
254  ERR ("%s", "Unable to transmit data. (TX)");
255  pnd->iLastError = res;
256  return false;
257  }
258 
259  if (!pn53x_check_error_frame_callback (pnd, abtRxBuf, szRxBufLen))
260  return false;
261 
262  // When the answer should be ignored, just return a successful result
263  if (pbtRx == NULL || pszRx == NULL)
264  return true;
265 
266  // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
267  if (szRxBufLen < 9) {
268  pnd->iLastError = DEINVAL;
269  return false;
270  }
271  // Remove the preceding and appending bytes 00 00 ff 00 ff 00 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
272  *pszRx = szRxBufLen - 9;
273  memcpy (pbtRx, abtRxBuf + 7, *pszRx);
274 
275  return true;
276 }
277 
278 void
279 pn532_uart_ack (const nfc_device_spec_t nds)
280 {
281 #ifdef DEBUG
282  PRINT_HEX ("TX", ack_frame, sizeof (ack_frame));
283 #endif
284  uart_send ((serial_port) nds, ack_frame, sizeof (ack_frame));
285 }
286 
287 bool
288 pn532_uart_wait_for_ack(const nfc_device_spec_t nds)
289 {
290  byte_t abtRx[RX_BUFFER_LEN];
291  size_t szRx = sizeof(ack_frame);
292  if (0 == uart_receive ((serial_port) nds, abtRx, &szRx)) {
293 #ifdef DEBUG
294  PRINT_HEX ("RX", abtRx, szRx);
295 #endif
296  } else {
297  ERR ("No ACK.");
298  return false;
299  }
300  if (0 != memcmp (ack_frame, abtRx, szRx))
301  return false;
302  return true;
303 }
304 
305 #define PN53X_RX_OVERHEAD 6
306 void
307 pn532_uart_wakeup (const nfc_device_spec_t nds)
308 {
309  byte_t abtRx[RX_BUFFER_LEN];
310  size_t szRx = PN53x_NORMAL_FRAME_OVERHEAD + 2;
314  const byte_t pncmd_pn532c106_wakeup_preamble[] =
315  { 0x55, 0x55, 0x00, 0x00, 0x00,
316  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317  0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00 }; // Here we send a SAMConfiguration command (Normal mode, the SAM is not used; this is the default mode)
318 #ifdef DEBUG
319  PRINT_HEX ("TX", pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble));
320 #endif
321  uart_send ((serial_port) nds, pncmd_pn532c106_wakeup_preamble, sizeof (pncmd_pn532c106_wakeup_preamble));
322 
323  pn532_uart_wait_for_ack(nds);
324 
325  if (0 == uart_receive ((serial_port) nds, abtRx, &szRx)) {
326 #ifdef DEBUG
327  PRINT_HEX ("RX", abtRx, szRx);
328 #endif
329  } else {
330  ERR ("Unable to wakeup the PN532.");
331  }
332 }
333 
334 bool
335 pn532_uart_check_communication (const nfc_device_spec_t nds, bool * success)
336 {
337  byte_t abtRx[RX_BUFFER_LEN];
338  const byte_t attempted_result[] =
339  { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0xf7, 0xD5, 0x01, 0x00, 'l', 'i', 'b', 'n', 'f', 'c',
340 0xbc, 0x00 };
341  size_t szRx = sizeof(attempted_result);
342  int res;
343 
345  const byte_t pncmd_communication_test[] =
346  { 0x00, 0x00, 0xff, 0x09, 0xf7, 0xd4, 0x00, 0x00, 'l', 'i', 'b', 'n', 'f', 'c', 0xbe, 0x00 };
347 
348  *success = false;
349 
350 #ifdef DEBUG
351  PRINT_HEX ("TX", pncmd_communication_test, sizeof (pncmd_communication_test));
352 #endif
353  res = uart_send ((serial_port) nds, pncmd_communication_test, sizeof (pncmd_communication_test));
354  if (res != 0) {
355  ERR ("%s", "Unable to transmit data. (TX)");
356  return false;
357  }
358 
359  res = uart_receive ((serial_port) nds, abtRx, &szRx);
360  if (res != 0) {
361  ERR ("%s", "Unable to receive data. (RX)");
362  return false;
363  }
364 #ifdef DEBUG
365  PRINT_HEX ("RX", abtRx, szRx);
366 #endif
367 
368  if (0 == memcmp (abtRx, attempted_result, sizeof (attempted_result)))
369  *success = true;
370 
371  return true;
372 }