Ejemplo n.º 1
0
static int
pn532_uart_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, int timeout)
{
  int res = 0;
  // Before sending anything, we need to discard from any junk bytes
  uart_flush_input(DRIVER_DATA(pnd)->port);

  switch (CHIP_DATA(pnd)->power_mode) {
    case LOWVBAT: {
      /** PN532C106 wakeup. */
      if ((res = pn532_uart_wakeup(pnd)) < 0) {
        return res;
      }
      // 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
      if ((res = pn532_SAMConfiguration(pnd, PSM_NORMAL, 1000)) < 0) {
        return res;
      }
    }
    break;
    case POWERDOWN: {
      if ((res = pn532_uart_wakeup(pnd)) < 0) {
        return res;
      }
    }
    break;
    case NORMAL:
      // Nothing to do :)
      break;
  };

  uint8_t  abtFrame[PN532_BUFFER_LEN] = { 0x00, 0x00, 0xff };       // Every packet must start with "00 00 ff"
  size_t szFrame = 0;

  if ((res = pn53x_build_frame(abtFrame, &szFrame, pbtData, szData)) < 0) {
    pnd->last_error = res;
    return pnd->last_error;
  }

  res = uart_send(DRIVER_DATA(pnd)->port, abtFrame, szFrame, timeout);
  if (res != 0) {
    log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to transmit data. (TX)");
    pnd->last_error = res;
    return pnd->last_error;
  }

  uint8_t abtRxBuf[6];
  res = uart_receive(DRIVER_DATA(pnd)->port, abtRxBuf, 6, 0, timeout);
  if (res != 0) {
    log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "Unable to read ACK");
    pnd->last_error = res;
    return pnd->last_error;
  }

  if (pn53x_check_ack_frame(pnd, abtRxBuf, sizeof(abtRxBuf)) == 0) {
    // The PN53x is running the sent command
  } else {
    return pnd->last_error;
  }
  return NFC_SUCCESS;
}
Ejemplo n.º 2
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,
          },
        },
      };