pn53x-sam.c 6.83 KB
Newer Older
1
/*-
2
 * Free/Libre Near Field Communication (NFC) library
3
 *
4 5 6 7 8 9 10 11
 * Libnfc historical contributors:
 * Copyright (C) 2009      Roel Verdult
 * Copyright (C) 2009-2013 Romuald Conty
 * Copyright (C) 2010-2012 Romain Tartière
 * Copyright (C) 2010-2013 Philippe Teuwen
 * Copyright (C) 2012-2013 Ludovic Rousseau
 * Additional contributors of this file:
 * Copyright (C) 2010      Emanuele Bertoldi
12
 *
13 14 15
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *  1) Redistributions of source code must retain the above copyright notice,
16
 *  this list of conditions and the following disclaimer.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *  2 )Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
32
 *
33
 * Note that this license only applies on the examples, NFC library itself is under LGPL
34 35 36 37
 *
 */

/**
38
 * @file pn53x-sam.c
Philippe Teuwen's avatar
Philippe Teuwen committed
39
 * @brief Configures the NFC device to communicate with a SAM (Secure Access Module).
40 41
 * @note This example requiers a PN532 with SAM connected using S2C interface
 * @see PN532 User manual
42
 */
43

44
#ifdef HAVE_CONFIG_H
45
#  include "config.h"
46 47 48 49
#endif // HAVE_CONFIG_H

#include <stdio.h>
#include <stdlib.h>
50
#include <time.h>
51
#include <unistd.h>
52

53
#include <nfc/nfc.h>
54

55 56
#include "utils/nfc-utils.h"
#include "libnfc/chips/pn53x.h"
57 58

#define MAX_FRAME_LEN 264
59
#define TIMEOUT 60              // secs.
60

Ludovic Rousseau's avatar
Ludovic Rousseau committed
61
static void
62
wait_one_minute(void)
63
{
64 65
  int     secs = 0;

66 67
  printf("|");
  fflush(stdout);
68 69

  while (secs < TIMEOUT) {
70
    sleep(1);
71
    secs++;
72 73
    printf(".");
    fflush(stdout);
74
  }
75

76
  printf("|\n");
77 78
}

79
int
80
main(int argc, const char *argv[])
81
{
82 83
  (void) argc;
  (void) argv;
84

85 86
  nfc_context *context;
  nfc_init(&context);
87 88 89 90
  if (context == NULL) {
    ERR("Unable to init libnfc (malloc)");
    exit(EXIT_FAILURE);
  }
91

92
  // Display libnfc version
93 94
  const char *acLibnfcVersion = nfc_version();
  printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
95

96
  // Open using the first available NFC device
97
  nfc_device *pnd;
98
  pnd = nfc_open(context, NULL);
99 100

  if (pnd == NULL) {
101
    ERR("%s", "Unable to open NFC device.");
102 103
    nfc_exit(context);
    exit(EXIT_FAILURE);
104 105
  }

106
  printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
107

108
  // Print the example's menu
109 110 111 112 113
  printf("\nSelect the communication mode:\n");
  printf("[1] Virtual card mode.\n");
  printf("[2] Wired card mode.\n");
  printf("[3] Dual card mode.\n");
  printf(">> ");
114

115
  // Take user's choice
116 117
  char    input = getchar();
  printf("\n");
118
  if ((input < '1') || (input > '3')) {
119
    ERR("%s", "Invalid selection.");
120 121 122
    nfc_close(pnd);
    nfc_exit(context);
    exit(EXIT_FAILURE);
123
  }
124 125 126 127 128 129 130

  /*
   * '1' -> "Virtual mode" (0x02)
   * '2' -> "Wired card" (0x03)
   * '3' -> "Dual card" (0x04)
   */
  int iMode = input - '0' + 0x01;
131 132
  pn532_sam_mode mode = iMode;

133
  // Connect with the SAM
134 135

  switch (mode) {
136
    case PSM_VIRTUAL_CARD: {
137 138 139
      // FIXME Its a private pn53x function
      if (pn532_SAMConfiguration(pnd, mode, 0) < 0) {
        nfc_perror(pnd, "pn53x_SAMConfiguration");
140 141 142
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
143
      }
144 145
      printf("Now the SAM is readable for 1 minute from an external reader.\n");
      wait_one_minute();
146 147
    }
    break;
148

149
    case PSM_WIRED_CARD: {
150
      // Set opened NFC device to initiator mode
151 152
      if (nfc_initiator_init_secure_element(pnd) < 0) {
        nfc_perror(pnd, "nfc_initiator_init_secure_element");
153 154 155
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
156
      }
157 158

      // Let the reader only try once to find a tag
159 160
      if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
        nfc_perror(pnd, "nfc_device_set_property_bool");
161 162 163
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
164
      }
165
      // Read the SAM's info
166
      const nfc_modulation nmSAM = {
167 168 169
        .nmt = NMT_ISO14443A,
        .nbr = NBR_106,
      };
170 171
      nfc_target nt;

172
      int res;
173 174
      if ((res = nfc_initiator_select_passive_target(pnd, nmSAM, NULL, 0, &nt)) < 0) {
        nfc_perror(pnd, "nfc_initiator_select_passive_target");
175 176 177
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
178
      } else if (res == 0) {
179
        ERR("No SAM found.");
180 181 182
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
183
      } else if (res == 1) {
184
        printf("The following ISO14443A tag (SAM) was found:\n");
185
        print_nfc_target(&nt, true);
186
      } else {
187
        ERR("%s", "More than one ISO14442 tag found as SAM.");
188 189 190
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
191
      }
192 193
    }
    break;
194

195
    case PSM_DUAL_CARD: {
196 197 198
      // FIXME Its a private pn53x function
      if (pn532_SAMConfiguration(pnd, mode, 0) < 0) {
        nfc_perror(pnd, "pn53x_SAMConfiguration");
199 200 201
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
202
      }
203
      uint8_t  abtRx[MAX_FRAME_LEN];
204

205
      nfc_target nt = {
206 207 208 209 210 211 212 213 214 215 216 217 218
        .nm = {
          .nmt = NMT_ISO14443A,
          .nbr = NBR_UNDEFINED,
        },
        .nti = {
          .nai = {
            .abtAtqa = { 0x04, 0x00 },
            .abtUid = { 0x08, 0xad, 0xbe, 0xef },
            .btSak = 0x20,
            .szUidLen = 4,
            .szAtsLen = 0,
          },
        },
219
      };
220 221 222
      printf("Now both, NFC device (configured as target) and SAM are readables from an external NFC initiator.\n");
      printf("Please note that NFC device (configured as target) stay in target mode until it receive RATS, ATR_REQ or proprietary command.\n");
      if (nfc_target_init(pnd, &nt, abtRx, sizeof(abtRx), 0) < 0) {
223
        nfc_perror(pnd, "nfc_target_init");
224 225 226
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
227 228
      }
      // wait_one_minute ();
229 230
    }
    break;
231
    case PSM_NORMAL:
232
      // This should not happend... nothing to do.
233
      break;
234
  }
235

236
  // Disconnect from the SAM
237
  pn532_SAMConfiguration(pnd, PSM_NORMAL, -1);
238

239
  // Close NFC device
240
  nfc_close(pnd);
241
  nfc_exit(context);
242
  exit(EXIT_SUCCESS);
243
}