Esempio n. 1
0
int
main(int argc, const char *argv[])
{
  (void) argc;
  (void) argv;

  nfc_context *context;
  nfc_init(&context);
  if (context == NULL) {
    ERR("Unable to init libnfc (malloc)");
    exit(EXIT_FAILURE);
  }

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

  // Open using the first available NFC device
  nfc_device *pnd;
  pnd = nfc_open(context, NULL);

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

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

  // Print the example's menu
  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(">> ");

  // Take user's choice
  int input = getchar();
  printf("\n");
  if ((input < '1') || (input > '3')) {
    ERR("%s", "Invalid selection.");
    nfc_close(pnd);
    nfc_exit(context);
    exit(EXIT_FAILURE);
  }

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

  // Connect with the SAM

  switch (mode) {
    case PSM_VIRTUAL_CARD: {
      // FIXME Its a private pn53x function
      if (pn532_SAMConfiguration(pnd, mode, 0) < 0) {
        nfc_perror(pnd, "pn53x_SAMConfiguration");
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
      printf("Now the SAM is readable for 1 minute from an external reader.\n");
      wait_one_minute();
    }
    break;

    case PSM_WIRED_CARD: {
      // Set opened NFC device to initiator mode
      if (nfc_initiator_init_secure_element(pnd) < 0) {
        nfc_perror(pnd, "nfc_initiator_init_secure_element");
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }

      // Let the reader only try once to find a tag
      if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
        nfc_perror(pnd, "nfc_device_set_property_bool");
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
      // Read the SAM's info
      const nfc_modulation nmSAM = {
        .nmt = NMT_ISO14443A,
        .nbr = NBR_106,
      };
      nfc_target nt;

      int res;
      if ((res = nfc_initiator_select_passive_target(pnd, nmSAM, NULL, 0, &nt)) < 0) {
        nfc_perror(pnd, "nfc_initiator_select_passive_target");
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      } else if (res == 0) {
        ERR("No SAM found.");
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      } else if (res == 1) {
        printf("The following ISO14443A tag (SAM) was found:\n");
        print_nfc_target(&nt, true);
      } else {
        ERR("%s", "More than one ISO14442 tag found as SAM.");
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
    }
    break;

    case PSM_DUAL_CARD: {
      // FIXME Its a private pn53x function
      if (pn532_SAMConfiguration(pnd, mode, 0) < 0) {
        nfc_perror(pnd, "pn53x_SAMConfiguration");
        nfc_close(pnd);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
      uint8_t  abtRx[MAX_FRAME_LEN];

      nfc_target nt = {
        .nm = {
          .nmt = NMT_ISO14443A,
          .nbr = NBR_UNDEFINED,
        },
        .nti = {
          .nai = {
            .abtAtqa = { 0x04, 0x00 },
            .abtUid = { 0x08, 0xad, 0xbe, 0xef },
            .btSak = 0x20,
            .szUidLen = 4,
            .szAtsLen = 0,
          },
        },
      };
int
main (int argc, const char *argv[])
{
  nfc_device_t *pnd;

  (void) argc;
  (void) argv;

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

  // Connect using the first available NFC device
  pnd = nfc_connect (NULL);

  if (pnd == NULL) {
    ERR ("%s", "Unable to connect to NFC device.");
    return EXIT_FAILURE;
  }

  printf ("Connected to NFC device: %s\n", pnd->acName);

  // Print the example's menu
  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 (">> ");

  // Take user's choice
  char    input = getchar ();
  int     mode = input - '0' + 1;
  printf ("\n");
  if (mode < VIRTUAL_CARD_MODE || mode > DUAL_CARD_MODE) {
    ERR ("%s", "Invalid selection.");
    return EXIT_FAILURE;
  }
  // Connect with the SAM
  sam_connection (pnd, mode);

  switch (mode) {
  case VIRTUAL_CARD_MODE:
    {
      // FIXME after the loop the device doesn't respond to host commands...
      printf ("Now the SAM is readable for 1 minute from an external reader.\n");
      wait_one_minute ();
    }
    break;

  case WIRED_CARD_MODE:
    {
      nfc_target_t nt;

      // Set connected NFC device to initiator mode
      nfc_initiator_init (pnd);

      // Drop the field for a while
      if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
        nfc_perror (pnd, "nfc_configure");
        exit (EXIT_FAILURE);
      }
      // Let the reader only try once to find a tag
      if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
        nfc_perror (pnd, "nfc_configure");
        exit (EXIT_FAILURE);
      }
      // Enable field so more power consuming cards can power themselves up
      if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
        nfc_perror (pnd, "nfc_configure");
        exit (EXIT_FAILURE);
      }
      // Read the SAM's info
      const nfc_modulation_t nmSAM = {
        .nmt = NMT_ISO14443A,
        .nbr = NBR_106,
      };
      if (!nfc_initiator_select_passive_target (pnd, nmSAM, NULL, 0, &nt)) {
        nfc_perror (pnd, "nfc_initiator_select_passive_target");
        ERR ("%s", "Reading of SAM info failed.");
        return EXIT_FAILURE;
      }

      printf ("The following ISO14443A tag (SAM) was found:\n\n");
      print_nfc_iso14443a_info (nt.nti.nai, true);
    }
    break;

  case DUAL_CARD_MODE:
    {
      byte_t  abtRx[MAX_FRAME_LEN];
      size_t  szRx;

      nfc_target_t nt = {
        .nm.nmt = NMT_ISO14443A,
        .nm.nbr = NBR_UNDEFINED,
        .nti.nai.abtAtqa = { 0x04, 0x00 },
        .nti.nai.abtUid = { 0x08, 0xad, 0xbe, 0xef },
        .nti.nai.btSak = 0x20,
        .nti.nai.szUidLen = 4,
        .nti.nai.szAtsLen = 0,
      };
      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, &szRx)) {
        nfc_perror(pnd, "nfc_target_init");
        return EXIT_FAILURE;
      }
      // wait_one_minute ();
    }
    break;
  }

  // Disconnect from the SAM
  sam_connection (pnd, NORMAL_MODE);

  // Disconnect from NFC device
  nfc_disconnect (pnd);

  return EXIT_SUCCESS;
}