Add NFCIP (NDEP) as experimental feature (Thanks to Fkooman).

This commit is contained in:
Romuald Conty 2009-09-03 13:47:26 +00:00
parent e92b8ab76f
commit 70ede60e30
6 changed files with 238 additions and 3 deletions

View file

@ -1,6 +1,6 @@
enable_pcsc_lite = @enable_pcsc_lite@
bin_PROGRAMS = nfc-anticol nfc-list nfc-mftool nfc-mfultool nfc-relay nfc-emulate
bin_PROGRAMS = nfc-anticol nfc-list nfc-mftool nfc-mfultool nfc-relay nfc-emulate nfcip-target nfcip-initiator
# set the include path found by configure
INCLUDES= $(all_includes)
@ -38,6 +38,12 @@ nfc_relay_LDADD = libnfc.la
nfc_emulate_SOURCES = emulate.c
nfc_emulate_LDADD = libnfc.la
nfcip_target_SOURCES = target.c
nfcip_target_LDADD = libnfc.la
nfcip_initiator_SOURCES = initiator.c
nfcip_initiator_LDADD = libnfc.la
dist_man_MANS = nfc-anticol.1 nfc-emulate.1 nfc-list.1 nfc-mftool.1 nfc-relay.1
#dist_man_MANS = $(man_MANS)
#EXTRA_DIST = $(man_MANS)

37
src/initiator.c Normal file
View file

@ -0,0 +1,37 @@
#include <stdio.h>
#include <string.h>
#include "libnfc.h"
int main(int argc, const char *argv[])
{
dev_info *pdi;
tag_info ti;
byte_t abtRecv[MAX_FRAME_LEN];
uint32_t uiRecvBits;
byte_t send[] = "Hello World!";
pdi = nfc_connect();
if (!pdi || !nfc_initiator_init(pdi)
|| !nfc_initiator_select_dep_target(pdi, IM_PASSIVE_DEP, NULL, 0,
NULL, 0, NULL, 0, &ti)) {
printf
("unable to connect, initialize, or select the target\n");
return 1;
}
printf("Sending : %s\n", send);
if (!nfc_initiator_transceive_dep_bytes(pdi,
send,
strlen(send), abtRecv,
&uiRecvBits)) {
printf("unable to send data\n");
return 1;
}
abtRecv[uiRecvBits] = 0;
printf("Received: %s\n", abtRecv);
nfc_initiator_deselect_tag(pdi);
nfc_disconnect(pdi);
return 0;
}

View file

@ -72,6 +72,8 @@ byte_t pncmd_rf_configure_retry_select [ 6] = { 0xD4,0x32,0x05 };
// Reader
byte_t pncmd_reader_list_passive [264] = { 0xD4,0x4A };
byte_t pncmd_reader_jump_for_dep [ 68] = { 0xD4,0x56 };
byte_t pncmd_reader_select [ 3] = { 0xD4,0x54 };
byte_t pncmd_reader_deselect [ 3] = { 0xD4,0x44,0x00 };
byte_t pncmd_reader_release [ 3] = { 0xD4,0x52,0x00 };
@ -81,6 +83,7 @@ byte_t pncmd_reader_auto_poll [ 5] = { 0xD4,0x60 };
// Target
byte_t pncmd_target_get_data [ 2] = { 0xD4,0x86 };
byte_t pncmd_target_set_data [264] = { 0xD4,0x8E };
byte_t pncmd_target_init [ 39] = { 0xD4,0x8C };
byte_t pncmd_target_virtual_card [ 4] = { 0xD4,0x14 };
byte_t pncmd_target_receive [ 2] = { 0xD4,0x88 };
@ -384,6 +387,53 @@ bool nfc_initiator_init(const dev_info* pdi)
return true;
}
bool nfc_initiator_select_dep_target(const dev_info* pdi, const init_modulation im, const byte_t* pbtPidData, const uint32_t uiPidDataLen, const byte_t* pbtNFCID3i, const uint32_t uiNFCID3iDataLen, const byte_t *pbtGbData, const uint32_t uiGbDataLen, tag_info* pti)
{
if(im == IM_ACTIVE_DEP) {
pncmd_reader_jump_for_dep[2] = 0x01; /* active DEP */
}
pncmd_reader_jump_for_dep[3] = 0x00; /* baud rate = 106kbps */
uint32_t offset = 5;
if(pbtPidData && im != IM_ACTIVE_DEP) { /* can't have passive initiator data when using active mode */
pncmd_reader_jump_for_dep[4] |= 0x01;
memcpy(pncmd_reader_jump_for_dep+offset,pbtPidData,uiPidDataLen);
offset+= uiPidDataLen;
}
if(pbtNFCID3i) {
pncmd_reader_jump_for_dep[4] |= 0x02;
memcpy(pncmd_reader_jump_for_dep+offset,pbtNFCID3i,uiNFCID3iDataLen);
offset+= uiNFCID3iDataLen;
}
if(pbtGbData) {
pncmd_reader_jump_for_dep[4] |= 0x04;
memcpy(pncmd_reader_jump_for_dep+offset,pbtGbData,uiGbDataLen);
offset+= uiGbDataLen;
}
// Try to find a target, call the transceive callback function of the current device
uiRxLen = MAX_FRAME_LEN;
if (!pdi->pdc->transceive(pdi->ds,pncmd_reader_jump_for_dep,5+uiPidDataLen+uiNFCID3iDataLen+uiGbDataLen,abtRx,&uiRxLen)) return false;
// some error occurred...
if (abtRx[0] != 0) return false;
// Make sure one target has been found, the PN53X returns 0x00 if none was available
if (abtRx[1] != 1) return false;
// Is a target info struct available
if (pti)
{
memcpy(pti->tid.NFCID3i,abtRx+2,10);
pti->tid.btDID = abtRx[12];
pti->tid.btBSt = abtRx[13];
pti->tid.btBRt = abtRx[14];
}
return true;
}
bool nfc_initiator_select_tag(const dev_info* pdi, const init_modulation im, const byte_t* pbtInitData, const uint32_t uiInitDataLen, tag_info* pti)
{
// Make sure we are dealing with a active device
@ -539,11 +589,36 @@ bool nfc_initiator_transceive_bits(const dev_info* pdi, const byte_t* pbtTx, con
return true;
}
bool nfc_initiator_transceive_dep_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen, byte_t* pbtRx, uint32_t* puiRxLen) {
// We can not just send bytes without parity if while the PN53X expects we handled them
if (!pdi->bPar) return false;
// Copy the data into the command frame
pncmd_reader_exchange_data[2] = 1; /* target number */
memcpy(pncmd_reader_exchange_data+3,pbtTx,uiTxLen);
// To transfer command frames bytes we can not have any leading bits, reset this to zero
if (!pn53x_set_tx_bits(pdi,0)) return false;
// Send the frame to the PN53X chip and get the answer
// We have to give the amount of bytes + (the two command bytes 0xD4, 0x42)
if (!pn53x_transceive(pdi,pncmd_reader_exchange_data,uiTxLen+3)) return false;
// Save the received byte count
*puiRxLen = uiRxLen-1;
// Copy the received bytes
memcpy(pbtRx,abtRx+1,*puiRxLen);
// Everything went successful
return true;
}
bool nfc_initiator_transceive_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen, byte_t* pbtRx, uint32_t* puiRxLen)
{
// We can not just send bytes without parity if while the PN53X expects we handled them
if (!pdi->bPar) return false;
// Copy the data into the command frame
memcpy(pncmd_exchange_raw_data+2,pbtTx,uiTxLen);
@ -700,6 +775,21 @@ bool nfc_target_receive_bits(const dev_info* pdi, byte_t* pbtRx, uint32_t* puiRx
return true;
}
bool nfc_target_receive_dep_bytes(const dev_info* pdi, byte_t* pbtRx, uint32_t* puiRxLen)
{
// Try to gather a received frame from the reader
if (!pn53x_transceive(pdi,pncmd_target_get_data,2)) return false;
// Save the received byte count
*puiRxLen = uiRxLen-1;
// Copy the received bytes
memcpy(pbtRx,abtRx+1,*puiRxLen);
// Everyting seems ok, return true
return true;
}
bool nfc_target_receive_bytes(const dev_info* pdi, byte_t* pbtRx, uint32_t* puiRxLen)
{
// Try to gather a received frame from the reader
@ -764,3 +854,19 @@ bool nfc_target_send_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint3
// Everyting seems ok, return true
return true;
}
bool nfc_target_send_dep_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen)
{
// We can not just send bytes without parity if while the PN53X expects we handled them
if (!pdi->bPar) return false;
// Copy the data into the command frame
memcpy(pncmd_target_set_data+2,pbtTx,uiTxLen);
// Try to send the bits to the reader
if (!pn53x_transceive(pdi,pncmd_target_set_data,uiTxLen+2)) return false;
// Everyting seems ok, return true
return true;
}

View file

@ -91,6 +91,20 @@ bool nfc_initiator_init(const dev_info* pdi);
*/
bool nfc_initiator_select_tag(const dev_info* pdi, const init_modulation im, const byte_t* pbtInitData, const uint32_t uiInitDataLen, tag_info* pti);
/**
* @fn nfc_initiator_select_dep_target(const dev_info *pdi, const init_modulation im, const byte_t *pbtPidData, const uint32_t uiPidDataLen, const byte_t *pbtNFCID3i, const uint32_t uiNFCID3iDataLen, const byte_t *pbtGbData, const uint32_t uiGbDataLen, tag_info * pti);
* @brief Select a target and request active or passive mode for DEP (Data Exchange Protocol)
* @return Returns true if action was successfully performed; otherwise returns false.
* @param pdi dev_info struct pointer that represent currently used device
* @param im Desired modulation (IM_ACTIVE_DEP or IM_PASSIVE_DEP for active, respectively passive mode)
* @param pbtPidData passive initiator data, 4 or 5 bytes long, (optional, only for IM_PASSIVE_DEP, can be NULL)
* @param pbtNFCID3i the NFCID3, 10 bytes long, of the initiator (optional, can be NULL)
* @param pbtGbData generic data of the initiator, max 48 bytes long, (optional, can be NULL)
*
* The NFC device will try to find the available target. The standards (ISO18092 and ECMA-340) describe the modulation that can be used for reader to passive communications.
* @note tag_info_dep will be returned when the target was acquired successfully.
*/
bool nfc_initiator_select_dep_target(const dev_info* pdi, const init_modulation im, const byte_t* pbtPidData, const uint32_t uiPidDataLen, const byte_t* pbtNFCID3i, const uint32_t uiNFCID3iDataLen, const byte_t *pbtGbData, const uint32_t uiGbDataLen, tag_info* pti);
/**
* @fn nfc_initiator_deselect_tag(const dev_info* pdi);
* @brief Deselect a selected passive or emulated tag
@ -126,6 +140,15 @@ bool nfc_initiator_transceive_bits(const dev_info* pdi, const byte_t* pbtTx, con
*/
bool nfc_initiator_transceive_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen, byte_t* pbtRx, uint32_t* puiRxLen);
/**
* @fn nfc_initiator_transceive_dep_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen, byte_t* pbtRx, uint32_t* puiRxLen)
* @brief Transceive data
* @return Returns true if action was successfully performed; otherwise returns false.
*
* The reader will transmit the supplied (data) bytes in pbtTx to the target (tag). It waits for the response and stores the received bytes in the pbtRx byte array. The difference between this function and nfc_initiator_transceive_bytes is that here pbtTx and pbtRx contain *only* the data sent and received and not any additional commands, that is all handled internally by the PN53X.
*/
bool nfc_initiator_transceive_dep_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen, byte_t* pbtRx, uint32_t* puiRxLen);
/**
* @fn nfc_initiator_mifare_cmd(const dev_info* pdi, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp)
* @brief Execute a MIFARE Classic Command
@ -168,6 +191,15 @@ bool nfc_target_receive_bits(const dev_info* pdi, byte_t* pbtRx, uint32_t* puiRx
*/
bool nfc_target_receive_bytes(const dev_info* pdi, byte_t* pbtRx, uint32_t* puiRxLen);
/**
* @fn nfc_target_receive_dep_bytes(const dev_info* pdi, byte_t* pbtRx, uint32_t* puiRxLen)
* @brief Receive data
* @return Returns true if action was successfully performed; otherwise returns false.
*
* The main receive function that returns the received data from a nearby reader. The difference between this function and nfc_target_receive_bytes is that here pbtRx contains *only* the data received and not any additional commands, that is all handled internally by the PN53X.
*/
bool nfc_target_receive_dep_bytes(const dev_info* pdi, byte_t* pbtRx, uint32_t* puiRxLen);
/**
* @fn nfc_target_send_bits(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxBits, const byte_t* pbtTxPar)
* @brief Send raw bit-frames
@ -186,5 +218,14 @@ bool nfc_target_send_bits(const dev_info* pdi, const byte_t* pbtTx, const uint32
*/
bool nfc_target_send_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen);
/**
* @fn nfc_target_send_dep_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen)
* @brief Send data
* @return Returns true if action was successfully performed; otherwise returns false.
*
* To communicate data to the reader, this function could be used. The difference between this function and nfc_target_send_bytes is that here pbtTx contains *only* the data sent and not any additional commands, that is all handled internally by the PN53X.
*/
bool nfc_target_send_dep_bytes(const dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen);
#endif // _LIBNFC_H_

31
src/target.c Normal file
View file

@ -0,0 +1,31 @@
#include <stdio.h>
#include "libnfc.h"
int main(int argc, const char *argv[])
{
byte_t abtRecv[MAX_FRAME_LEN];
uint32_t uiRecvBits;
byte_t send[] = "Hello Mars!";
dev_info *pdi = nfc_connect();
if (!pdi || !nfc_target_init(pdi, abtRecv, &uiRecvBits)) {
printf("unable to connect or initialize\n");
return 1;
}
if (!nfc_target_receive_dep_bytes(pdi, abtRecv, &uiRecvBits)) {
printf("unable to receive data\n");
return 1;
}
abtRecv[uiRecvBits] = 0;
printf("Received: %s\n", abtRecv);
printf("Sending : %s\n", send);
if (!nfc_target_send_dep_bytes(pdi, send, 11)) {
printf("unable to send data\n");
return 1;
}
nfc_disconnect(pdi);
return 0;
}

View file

@ -122,9 +122,22 @@ typedef enum {
/** ISO14443-B http://en.wikipedia.org/wiki/ISO/IEC_14443 */
IM_ISO14443B_106 = 0x03,
/** Jewel Topaz (Innovision Research & Development) */
IM_JEWEL_106 = 0x04
IM_JEWEL_106 = 0x04,
/** Active DEP */
IM_ACTIVE_DEP = 0x05,
/** Passive DEP */
IM_PASSIVE_DEP = 0x06,
}init_modulation;
typedef struct {
byte_t NFCID3i[10];
byte_t btDID;
byte_t btBSt;
byte_t btBRt;
}tag_info_dep;
typedef struct {
byte_t abtAtqa[2];
byte_t btSak;
@ -164,6 +177,7 @@ typedef union {
tag_info_felica tif;
tag_info_iso14443b tib;
tag_info_jewel tij;
tag_info_dep tid;
}tag_info;
////////////////////////////////////////////////////////////////////