2010-06-15 17:05:40 +02:00
|
|
|
/*-
|
|
|
|
* Public platform independent Near Field Communication (NFC) library
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009, Roel Verdult
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU Lesser General Public License as published by the
|
|
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
* option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file nfc-sam.c
|
|
|
|
* @brief Configure the reader to comunicate with a SAM (Secure Access Module).
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif // HAVE_CONFIG_H
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2010-06-16 13:21:27 +02:00
|
|
|
#include <time.h>
|
2010-06-15 17:05:40 +02:00
|
|
|
|
2010-06-16 14:12:31 +02:00
|
|
|
// Needed by sleep() under Unix
|
|
|
|
#include <unistd.h>
|
|
|
|
// FIXME What about sleep() in Windows ?
|
|
|
|
|
2010-06-15 17:05:40 +02:00
|
|
|
#include <nfc/nfc.h>
|
|
|
|
#include <nfc/nfc-messages.h>
|
|
|
|
#include "nfc-utils.h"
|
|
|
|
|
|
|
|
#define MAX_FRAME_LEN 264
|
|
|
|
|
2010-06-16 13:21:27 +02:00
|
|
|
#define NORMAL_MODE 1
|
2010-06-15 17:05:40 +02:00
|
|
|
#define VIRTUAL_CARD_MODE 2
|
|
|
|
#define WIRED_CARD_MODE 3
|
|
|
|
#define DUAL_CARD_MODE 4
|
|
|
|
|
2010-06-16 13:21:27 +02:00
|
|
|
bool sam_connection(nfc_device_t* pnd, int mode)
|
2010-06-15 17:05:40 +02:00
|
|
|
{
|
2010-06-16 13:21:27 +02:00
|
|
|
byte_t pncmd_sam_config[] = { 0xD4,0x14,0x00,0x00 };
|
2010-06-15 17:05:40 +02:00
|
|
|
|
|
|
|
byte_t abtRx[MAX_FRAME_LEN];
|
|
|
|
size_t szRxLen;
|
|
|
|
|
2010-06-16 13:21:27 +02:00
|
|
|
// Only the VIRTUAL_CARD_MODE requires 4 bytes.
|
|
|
|
int size = sizeof(pncmd_sam_config)-((mode == VIRTUAL_CARD_MODE) ? 0 : 1);
|
|
|
|
pncmd_sam_config[2] = mode;
|
|
|
|
|
2010-07-26 10:55:43 +02:00
|
|
|
if (!pnd->pdc->transceive(pnd->nds,pncmd_sam_config,size,abtRx,&szRxLen)) {
|
|
|
|
ERR("%s %d", "Unable to execute SAMConfiguration command with mode byte:", mode);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2010-06-16 13:21:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void wait_one_minute()
|
|
|
|
{
|
|
|
|
int secs = 0;
|
|
|
|
|
|
|
|
printf("|");
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
while (secs < 60)
|
|
|
|
{
|
|
|
|
sleep(1);
|
|
|
|
secs += 1;
|
|
|
|
printf(".");
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
2010-06-15 17:05:40 +02:00
|
|
|
|
2010-06-16 13:21:27 +02:00
|
|
|
printf("|\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, const char* argv[])
|
|
|
|
{
|
|
|
|
nfc_device_t* pnd;
|
2010-06-15 17:05:40 +02:00
|
|
|
|
2010-07-24 20:54:50 +02:00
|
|
|
(void)(argc, argv);
|
|
|
|
|
2010-06-15 17:05:40 +02:00
|
|
|
// 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) {
|
2010-07-26 10:55:43 +02:00
|
|
|
ERR("%s", "Unable to connect to NFC device.");
|
|
|
|
return EXIT_FAILURE;
|
2010-06-15 17:05:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
printf("Connected to NFC reader: %s\n",pnd->acName);
|
|
|
|
|
2010-06-16 13:21:27 +02:00
|
|
|
// Print the example's menu
|
2010-06-15 17:05:40 +02:00
|
|
|
printf("\nSelect the comunication mode:\n");
|
|
|
|
printf("[1] Virtual card mode.\n");
|
|
|
|
printf("[2] Wired card mode.\n");
|
|
|
|
printf("[3] Dual card mode.\n");
|
|
|
|
printf(">> ");
|
|
|
|
|
2010-06-16 13:21:27 +02:00
|
|
|
// Take user's choice
|
2010-06-15 17:05:40 +02:00
|
|
|
char input = getchar();
|
|
|
|
int mode = input-'0'+1;
|
|
|
|
printf("\n");
|
2010-06-16 13:32:16 +02:00
|
|
|
if (mode < VIRTUAL_CARD_MODE || mode > DUAL_CARD_MODE) {
|
2010-07-26 10:55:43 +02:00
|
|
|
ERR("%s", "Invalid selection.");
|
|
|
|
return EXIT_FAILURE;
|
2010-06-16 13:32:16 +02:00
|
|
|
}
|
2010-06-15 17:05:40 +02:00
|
|
|
|
2010-06-16 13:21:27 +02:00
|
|
|
// Connect with the SAM
|
|
|
|
sam_connection(pnd, mode);
|
2010-06-15 17:05:40 +02:00
|
|
|
|
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case VIRTUAL_CARD_MODE:
|
|
|
|
{
|
2010-06-16 13:34:55 +02:00
|
|
|
// FIXME: after the loop the reader doesn't respond to host commands...
|
2010-06-16 13:21:27 +02:00
|
|
|
printf("Now the SAM is readable for 1 minute from an external reader.\n");
|
|
|
|
wait_one_minute();
|
2010-06-15 17:05:40 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WIRED_CARD_MODE:
|
2010-06-16 13:21:27 +02:00
|
|
|
{
|
|
|
|
nfc_target_info_t nti;
|
|
|
|
|
2010-06-16 13:40:23 +02:00
|
|
|
// Set connected NFC device to initiator mode
|
|
|
|
nfc_initiator_init(pnd);
|
|
|
|
|
|
|
|
// Drop the field for a while
|
|
|
|
nfc_configure(pnd,NDO_ACTIVATE_FIELD,false);
|
|
|
|
|
|
|
|
// Let the reader only try once to find a tag
|
|
|
|
nfc_configure(pnd,NDO_INFINITE_SELECT,false);
|
|
|
|
|
|
|
|
// Configure the CRC and Parity settings
|
|
|
|
nfc_configure(pnd,NDO_HANDLE_CRC,true);
|
|
|
|
nfc_configure(pnd,NDO_HANDLE_PARITY,true);
|
|
|
|
|
|
|
|
// Enable field so more power consuming cards can power themselves up
|
|
|
|
nfc_configure(pnd,NDO_ACTIVATE_FIELD,true);
|
|
|
|
|
2010-06-16 13:21:27 +02:00
|
|
|
// Read the SAM's info
|
2010-07-21 12:37:37 +02:00
|
|
|
if (!nfc_initiator_select_passive_target(pnd,NM_ISO14443A_106,NULL,0,&nti)) {
|
2010-06-16 13:32:16 +02:00
|
|
|
ERR("%s", "Reading of SAM info failed.");
|
2010-06-16 13:21:27 +02:00
|
|
|
return EXIT_FAILURE;
|
2010-06-16 13:32:16 +02:00
|
|
|
}
|
2010-06-16 13:21:27 +02:00
|
|
|
|
2010-06-16 13:32:16 +02:00
|
|
|
printf("The following ISO14443A tag (SAM) was found:\n\n");
|
2010-06-16 13:21:27 +02:00
|
|
|
print_nfc_iso14443a_info (nti.nai);
|
2010-06-15 17:05:40 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DUAL_CARD_MODE:
|
|
|
|
{
|
2010-06-16 13:21:27 +02:00
|
|
|
byte_t abtRx[MAX_FRAME_LEN];
|
|
|
|
size_t szRxLen;
|
|
|
|
|
2010-07-26 10:55:43 +02:00
|
|
|
// FIXME: it does not work as expected...Probably the issue is in "nfc_target_init"
|
|
|
|
// which doesn't provide a way to set custom data for SENS_RES, NFCID1, SEL_RES, etc.
|
2010-06-16 13:21:27 +02:00
|
|
|
if (!nfc_target_init(pnd,abtRx,&szRxLen))
|
|
|
|
return EXIT_FAILURE;
|
2010-07-26 10:55:43 +02:00
|
|
|
|
2010-06-16 13:21:27 +02:00
|
|
|
printf("Now both the NFC reader and SAM are readable for 1 minute from an external reader.\n");
|
|
|
|
wait_one_minute();
|
2010-06-15 17:05:40 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2010-06-16 13:21:27 +02:00
|
|
|
|
2010-07-26 10:55:43 +02:00
|
|
|
// Disconnect from the SAM
|
2010-06-16 13:21:27 +02:00
|
|
|
sam_connection(pnd, NORMAL_MODE);
|
2010-06-15 17:05:40 +02:00
|
|
|
|
|
|
|
// Disconnect from NFC device
|
|
|
|
nfc_disconnect(pnd);
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|