libnfc  1.8.0
pn53x-sam.c
Go to the documentation of this file.
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) 2010 Emanuele Bertoldi
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are met:
16  * 1) Redistributions of source code must retain the above copyright notice,
17  * this list of conditions and the following disclaimer.
18  * 2 )Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Note that this license only applies on the examples, NFC library itself is under LGPL
35  *
36  */
37 
45 #ifdef HAVE_CONFIG_H
46 # include "config.h"
47 #endif // HAVE_CONFIG_H
48 
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <time.h>
52 #include <unistd.h>
53 
54 #include <nfc/nfc.h>
55 
56 #include "utils/nfc-utils.h"
57 #include "libnfc/chips/pn53x.h"
58 
59 #define MAX_FRAME_LEN 264
60 #define TIMEOUT 60 // secs.
61 
62 static void
63 wait_one_minute(void)
64 {
65  int secs = 0;
66 
67  printf("|");
68  fflush(stdout);
69 
70  while (secs < TIMEOUT) {
71  sleep(1);
72  secs++;
73  printf(".");
74  fflush(stdout);
75  }
76 
77  printf("|\n");
78 }
79 
80 int
81 main(int argc, const char *argv[])
82 {
83  (void) argc;
84  (void) argv;
85 
86  nfc_context *context;
87  nfc_init(&context);
88  if (context == NULL) {
89  ERR("Unable to init libnfc (malloc)");
90  exit(EXIT_FAILURE);
91  }
92 
93  // Display libnfc version
94  const char *acLibnfcVersion = nfc_version();
95  printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
96 
97  // Open using the first available NFC device
98  nfc_device *pnd;
99  pnd = nfc_open(context, NULL);
100 
101  if (pnd == NULL) {
102  ERR("%s", "Unable to open NFC device.");
103  nfc_exit(context);
104  exit(EXIT_FAILURE);
105  }
106 
107  printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
108 
109  // Print the example's menu
110  printf("\nSelect the communication mode:\n");
111  printf("[1] Virtual card mode.\n");
112  printf("[2] Wired card mode.\n");
113  printf("[3] Dual card mode.\n");
114  printf(">> ");
115 
116  // Take user's choice
117  int input = getchar();
118  printf("\n");
119  if ((input < '1') || (input > '3')) {
120  ERR("%s", "Invalid selection.");
121  nfc_close(pnd);
122  nfc_exit(context);
123  exit(EXIT_FAILURE);
124  }
125 
126  /*
127  * '1' -> "Virtual mode" (0x02)
128  * '2' -> "Wired card" (0x03)
129  * '3' -> "Dual card" (0x04)
130  */
131  int iMode = input - '0' + 0x01;
132  pn532_sam_mode mode = iMode;
133 
134  // Connect with the SAM
135 
136  switch (mode) {
137  case PSM_VIRTUAL_CARD: {
138  // FIXME Its a private pn53x function
139  if (pn532_SAMConfiguration(pnd, mode, 0) < 0) {
140  nfc_perror(pnd, "pn53x_SAMConfiguration");
141  nfc_close(pnd);
142  nfc_exit(context);
143  exit(EXIT_FAILURE);
144  }
145  printf("Now the SAM is readable for 1 minute from an external reader.\n");
146  wait_one_minute();
147  }
148  break;
149 
150  case PSM_WIRED_CARD: {
151  // Set opened NFC device to initiator mode
152  if (nfc_initiator_init_secure_element(pnd) < 0) {
153  nfc_perror(pnd, "nfc_initiator_init_secure_element");
154  nfc_close(pnd);
155  nfc_exit(context);
156  exit(EXIT_FAILURE);
157  }
158 
159  // Let the reader only try once to find a tag
160  if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
161  nfc_perror(pnd, "nfc_device_set_property_bool");
162  nfc_close(pnd);
163  nfc_exit(context);
164  exit(EXIT_FAILURE);
165  }
166  // Read the SAM's info
167  const nfc_modulation nmSAM = {
168  .nmt = NMT_ISO14443A,
169  .nbr = NBR_106,
170  };
171  nfc_target nt;
172 
173  int res;
174  if ((res = nfc_initiator_select_passive_target(pnd, nmSAM, NULL, 0, &nt)) < 0) {
175  nfc_perror(pnd, "nfc_initiator_select_passive_target");
176  nfc_close(pnd);
177  nfc_exit(context);
178  exit(EXIT_FAILURE);
179  } else if (res == 0) {
180  ERR("No SAM found.");
181  nfc_close(pnd);
182  nfc_exit(context);
183  exit(EXIT_FAILURE);
184  } else if (res == 1) {
185  printf("The following ISO14443A tag (SAM) was found:\n");
186  print_nfc_target(&nt, true);
187  } else {
188  ERR("%s", "More than one ISO14442 tag found as SAM.");
189  nfc_close(pnd);
190  nfc_exit(context);
191  exit(EXIT_FAILURE);
192  }
193  }
194  break;
195 
196  case PSM_DUAL_CARD: {
197  // FIXME Its a private pn53x function
198  if (pn532_SAMConfiguration(pnd, mode, 0) < 0) {
199  nfc_perror(pnd, "pn53x_SAMConfiguration");
200  nfc_close(pnd);
201  nfc_exit(context);
202  exit(EXIT_FAILURE);
203  }
204  uint8_t abtRx[MAX_FRAME_LEN];
205 
206  nfc_target nt = {
207  .nm = {
208  .nmt = NMT_ISO14443A,
209  .nbr = NBR_UNDEFINED,
210  },
211  .nti = {
212  .nai = {
213  .abtAtqa = { 0x04, 0x00 },
214  .abtUid = { 0x08, 0xad, 0xbe, 0xef },
215  .btSak = 0x20,
216  .szUidLen = 4,
217  .szAtsLen = 0,
218  },
219  },
220  };
221  printf("Now both, NFC device (configured as target) and SAM are readables from an external NFC initiator.\n");
222  printf("Please note that NFC device (configured as target) stay in target mode until it receive RATS, ATR_REQ or proprietary command.\n");
223  if (nfc_target_init(pnd, &nt, abtRx, sizeof(abtRx), 0) < 0) {
224  nfc_perror(pnd, "nfc_target_init");
225  nfc_close(pnd);
226  nfc_exit(context);
227  exit(EXIT_FAILURE);
228  }
229  // wait_one_minute ();
230  }
231  break;
232  case PSM_NORMAL:
233  // This should not happend... nothing to do.
234  break;
235  }
236 
237  // Disconnect from the SAM
238  pn532_SAMConfiguration(pnd, PSM_NORMAL, -1);
239 
240  // Close NFC device
241  nfc_close(pnd);
242  nfc_exit(context);
243  exit(EXIT_SUCCESS);
244 }
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
Definition: nfc.c:1209
void nfc_close(nfc_device *pnd)
Close from a NFC device.
Definition: nfc.c:339
nfc_device * nfc_open(nfc_context *context, const nfc_connstring connstring)
Open a NFC device.
Definition: nfc.c:277
void nfc_perror(const nfc_device *pnd, const char *pcString)
Display the last error occured on a nfc_device.
Definition: nfc.c:1183
int nfc_initiator_init_secure_element(nfc_device *pnd)
Initialize NFC device as initiator with its secure element as target (reader)
Definition: nfc.c:533
int nfc_initiator_select_passive_target(nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt)
Select a passive or emulated tag.
Definition: nfc.c:562
void nfc_exit(nfc_context *context)
Deinitialize libnfc. Should be called after closing all open devices and before your application term...
Definition: nfc.c:248
void nfc_init(nfc_context **context)
Initialize libnfc. This function must be called before calling any other libnfc function.
Definition: nfc.c:231
const char * nfc_version(void)
Returns the library version.
Definition: nfc.c:1319
int nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
Set a device's boolean-property value.
Definition: nfc.c:466
int nfc_target_init(nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const size_t szRx, int timeout)
Initialize NFC device as an emulated tag.
Definition: nfc.c:978
@ NP_INFINITE_SELECT
Definition: nfc-types.h:115
Provide some examples shared functions like print, parity calculation, options parsing.
#define ERR(...)
Print a error message.
Definition: nfc-utils.h:85
libnfc interface
NFC library context Struct which contains internal options, references, pointers, etc....
Definition: nfc-internal.h:175
NFC device information.
Definition: nfc-internal.h:190
NFC modulation structure.
Definition: nfc-types.h:342
NFC target structure.
Definition: nfc-types.h:351