updating svn mess
This commit is contained in:
parent
bbae6dcee5
commit
7e221462a0
10 changed files with 962 additions and 863 deletions
187
acr122.c
187
acr122.c
|
@ -1,187 +0,0 @@
|
|||
/*
|
||||
|
||||
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 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 General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <winscard.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "acr122.h"
|
||||
#include "bitutils.h"
|
||||
|
||||
#define SCARD_OPERATION_SUCCESS 0x61
|
||||
#define SCARD_OPERATION_ERROR 0x63
|
||||
|
||||
#define FIRMWARE_TEXT "ACR122U10" // ACR122U101(ACS), ACR122U102(Tikitag)
|
||||
|
||||
#define ACR122_WRAP_LEN 5
|
||||
#define ACR122_COMMAND_LEN 266
|
||||
|
||||
#define ACR122_RESPONSE_LEN 268
|
||||
|
||||
#define MAX_READERS 16
|
||||
|
||||
static SCARDCONTEXT hCtx = null;
|
||||
|
||||
static byte abtTxBuf[ACR122_WRAP_LEN+ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00 };
|
||||
static byte abtRxCmd[5] = { 0xFF,0xC0,0x00,0x00 };
|
||||
static byte uiRxCmdLen = sizeof(abtRxCmd);
|
||||
static byte abtRxBuf[ACR122_RESPONSE_LEN];
|
||||
static ulong ulRxBufLen;
|
||||
static byte abtGetFw[5] = { 0xFF,0x00,0x48,0x00,0x00 };
|
||||
static byte abtLed[9] = { 0xFF,0x00,0x40,0x05,0x04,0x00,0x00,0x00,0x00 };
|
||||
|
||||
dev_id acr122_connect(const ui32 uiDeviceIndex)
|
||||
{
|
||||
SCARDHANDLE hCard = null;
|
||||
char* pacReaders[MAX_READERS];
|
||||
char acList[256+64*MAX_READERS];
|
||||
ulong ulListLen = sizeof(acList);
|
||||
ulong ulActiveProtocol = 0;
|
||||
ui32 uiPos;
|
||||
ui32 uiReaderCount;
|
||||
ui32 uiReader;
|
||||
ui32 uiReaderIndex;
|
||||
|
||||
// Clear the reader list
|
||||
memset(acList,0x00,ulListLen);
|
||||
|
||||
// Test if context succeeded
|
||||
if (SCardEstablishContext(SCARD_SCOPE_USER,null,null,&hCtx) != SCARD_S_SUCCESS) return INVALID_DEVICE_ID;
|
||||
|
||||
// Retrieve the string array of all available pcsc readers
|
||||
if (SCardListReaders(hCtx,null,acList,(void*)&ulListLen) != SCARD_S_SUCCESS) return INVALID_DEVICE_ID;
|
||||
|
||||
pacReaders[0] = acList;
|
||||
uiReaderCount = 1;
|
||||
for (uiPos=0; uiPos<ulListLen; uiPos++)
|
||||
{
|
||||
// Make sure don't break out of our reader array
|
||||
if (uiReaderCount == MAX_READERS) break;
|
||||
|
||||
// Test if there is a next reader available
|
||||
if (acList[uiPos] == 0x00)
|
||||
{
|
||||
// Test if we are at the end of the list
|
||||
if (acList[uiPos+1] == 0x00)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Store the position of the next reader and search for more readers
|
||||
pacReaders[uiReaderCount] = acList+uiPos+1;
|
||||
uiReaderCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the reader index we are seaching for
|
||||
uiReaderIndex = uiDeviceIndex;
|
||||
|
||||
// Iterate through all readers and try to find the ACR122 on requested index
|
||||
for (uiReader=0; uiReader<uiReaderCount; uiReader++)
|
||||
{
|
||||
// Test if we were able to connect to the "emulator" card
|
||||
if (SCardConnect(hCtx,pacReaders[uiReader],SCARD_SHARE_SHARED,SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,&hCard,(void*)&ulActiveProtocol) == SCARD_S_SUCCESS)
|
||||
{
|
||||
if (strstr(acr122_firmware((void*)hCard),FIRMWARE_TEXT) != null)
|
||||
{
|
||||
// We found a occurence, test if it has the right index
|
||||
if (uiReaderIndex == 0)
|
||||
{
|
||||
// Done, we found the reader we are looking for
|
||||
return (void*)hCard;
|
||||
} else {
|
||||
// Let's look for the next reader
|
||||
uiReaderIndex--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Too bad, the reader could not be located;
|
||||
return INVALID_DEVICE_ID;
|
||||
}
|
||||
|
||||
void acr122_disconnect(const dev_id di)
|
||||
{
|
||||
SCardDisconnect((SCARDHANDLE)di,SCARD_LEAVE_CARD);
|
||||
}
|
||||
|
||||
bool acr122_transceive(const dev_id di, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen)
|
||||
{
|
||||
if (di == null) return false;
|
||||
|
||||
// Make sure the command does not overflow the send buffer
|
||||
if (uiTxLen > ACR122_COMMAND_LEN) return false;
|
||||
|
||||
// Store the length of the command we are going to send
|
||||
abtTxBuf[4] = uiTxLen;
|
||||
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Tx: ");
|
||||
print_hex(pbtTx,uiTxLen);
|
||||
#endif
|
||||
// Prepare and transmit the send buffer
|
||||
memcpy(abtTxBuf+5,pbtTx,uiTxLen);
|
||||
ulRxBufLen = sizeof(abtRxBuf);
|
||||
if (SCardTransmit((SCARDHANDLE)di,SCARD_PCI_T0,abtTxBuf,uiTxLen+5,null,abtRxBuf,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false;
|
||||
|
||||
// Make sure we received the byte-count we expected
|
||||
if (ulRxBufLen != 2) return false;
|
||||
|
||||
// Check if the operation was successful, so an answer is available
|
||||
if (*abtRxBuf == SCARD_OPERATION_ERROR) return false;
|
||||
|
||||
// Retrieve the response bytes
|
||||
abtRxCmd[4] = abtRxBuf[1];
|
||||
ulRxBufLen = sizeof(abtRxBuf);
|
||||
if (SCardTransmit((SCARDHANDLE)di,SCARD_PCI_T0,abtRxCmd,uiRxCmdLen,null,abtRxBuf,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false;
|
||||
|
||||
// When the answer should be ignored, just return true
|
||||
if (pbtRx == null || puiRxLen == null) return true;
|
||||
|
||||
// Make sure we have an emulated answer that fits the return buffer
|
||||
if (ulRxBufLen < 4 || (ulRxBufLen-4) > *puiRxLen) return false;
|
||||
|
||||
// Wipe out the 4 APDU emulation bytes: D5 4B .. .. .. 90 00
|
||||
*puiRxLen = ulRxBufLen-4;
|
||||
memcpy(pbtRx,abtRxBuf+2,*puiRxLen);
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Rx: ");
|
||||
print_hex(pbtRx,*puiRxLen);
|
||||
#endif
|
||||
|
||||
// Transmission went successful
|
||||
return true;
|
||||
}
|
||||
|
||||
char* acr122_firmware(const dev_id di)
|
||||
{
|
||||
static char abtFw[11];
|
||||
ulong ulFwLen = sizeof(abtFw);
|
||||
memset(abtFw,0x00,ulFwLen);
|
||||
SCardTransmit((SCARDHANDLE)di,SCARD_PCI_T0,abtGetFw,sizeof(abtGetFw),null,(byte*)abtFw,(void*)&ulFwLen);
|
||||
return abtFw;
|
||||
}
|
||||
|
||||
bool acr122_led_red(const dev_id di, bool bOn)
|
||||
{
|
||||
byte abtBuf[2];
|
||||
ulong ulBufLen = sizeof(abtBuf);
|
||||
return (SCardTransmit((SCARDHANDLE)di,SCARD_PCI_T0,abtLed,sizeof(abtLed),null,(byte*)abtBuf,(void*)&ulBufLen) == SCARD_S_SUCCESS);
|
||||
}
|
||||
|
269
dev_acr122.c
Normal file
269
dev_acr122.c
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
|
||||
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 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 General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#include <winscard.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "dev_acr122.h"
|
||||
#include "bitutils.h"
|
||||
|
||||
// WINDOWS: #define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE SCARD_CTL_CODE(3500)
|
||||
#define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE (((0x31) << 16) | ((3500) << 2))
|
||||
#define SCARD_OPERATION_SUCCESS 0x61
|
||||
#define SCARD_OPERATION_ERROR 0x63
|
||||
|
||||
#ifndef SCARD_PROTOCOL_UNDEFINED
|
||||
#define SCARD_PROTOCOL_UNDEFINED SCARD_PROTOCOL_UNSET
|
||||
#endif
|
||||
|
||||
#define FIRMWARE_TEXT "ACR122U" // Tested on: ACR122U101(ACS), ACR122U102(Tikitag), ACR122U203(ACS)
|
||||
|
||||
#define ACR122_WRAP_LEN 5
|
||||
#define ACR122_COMMAND_LEN 266
|
||||
#define ACR122_RESPONSE_LEN 268
|
||||
#define MAX_READERS 16
|
||||
|
||||
typedef struct {
|
||||
SCARDCONTEXT hCtx;
|
||||
SCARDHANDLE hCard;
|
||||
SCARD_IO_REQUEST ioCard;
|
||||
} dev_spec_acr122;
|
||||
|
||||
static byte abtTxBuf[ACR122_WRAP_LEN+ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00 };
|
||||
static byte abtRxCmd[5] = { 0xFF,0xC0,0x00,0x00 };
|
||||
static byte uiRxCmdLen = sizeof(abtRxCmd);
|
||||
static byte abtRxBuf[ACR122_RESPONSE_LEN];
|
||||
static ulong ulRxBufLen;
|
||||
static byte abtGetFw[5] = { 0xFF,0x00,0x48,0x00,0x00 };
|
||||
static byte abtLed[9] = { 0xFF,0x00,0x40,0x05,0x04,0x00,0x00,0x00,0x00 };
|
||||
|
||||
dev_info* dev_acr122_connect(const ui32 uiIndex)
|
||||
{
|
||||
char* pacReaders[MAX_READERS];
|
||||
char acList[256+64*MAX_READERS];
|
||||
ulong ulListLen = sizeof(acList);
|
||||
ui32 uiPos;
|
||||
ui32 uiReaderCount;
|
||||
ui32 uiReader;
|
||||
ui32 uiDevIndex;
|
||||
dev_info* pdi;
|
||||
dev_spec_acr122* pdsa;
|
||||
dev_spec_acr122 dsa;
|
||||
char* pcFirmware;
|
||||
|
||||
// Clear the reader list
|
||||
memset(acList,0x00,ulListLen);
|
||||
|
||||
// Test if context succeeded
|
||||
if (SCardEstablishContext(SCARD_SCOPE_USER,null,null,&(dsa.hCtx)) != SCARD_S_SUCCESS) return INVALID_DEVICE_INFO;
|
||||
|
||||
// Retrieve the string array of all available pcsc readers
|
||||
if (SCardListReaders(dsa.hCtx,null,acList,(void*)&ulListLen) != SCARD_S_SUCCESS) return INVALID_DEVICE_INFO;
|
||||
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Found the following PCSC device(s)\n");
|
||||
printf("- %s\n",acList);
|
||||
#endif
|
||||
|
||||
pacReaders[0] = acList;
|
||||
uiReaderCount = 1;
|
||||
for (uiPos=0; uiPos<ulListLen; uiPos++)
|
||||
{
|
||||
// Make sure don't break out of our reader array
|
||||
if (uiReaderCount == MAX_READERS) break;
|
||||
|
||||
// Test if there is a next reader available
|
||||
if (acList[uiPos] == 0x00)
|
||||
{
|
||||
// Test if we are at the end of the list
|
||||
if (acList[uiPos+1] == 0x00)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Store the position of the next reader and search for more readers
|
||||
pacReaders[uiReaderCount] = acList+uiPos+1;
|
||||
uiReaderCount++;
|
||||
|
||||
// Debug info
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("- %s\n",acList+uiPos+1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the device index we are seaching for
|
||||
uiDevIndex = uiIndex;
|
||||
|
||||
// Iterate through all readers and try to find the ACR122 on requested index
|
||||
for (uiReader=0; uiReader<uiReaderCount; uiReader++)
|
||||
{
|
||||
// Test if we were able to connect to the "emulator" card
|
||||
if (SCardConnect(dsa.hCtx,pacReaders[uiReader],SCARD_SHARE_EXCLUSIVE,SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,&(dsa.hCard),(void*)&(dsa.ioCard.dwProtocol)) != SCARD_S_SUCCESS)
|
||||
{
|
||||
// Connect to ACR122 firmware version >2.0
|
||||
if (SCardConnect(dsa.hCtx,pacReaders[uiReader],SCARD_SHARE_DIRECT,0,&(dsa.hCard),(void*)&(dsa.ioCard.dwProtocol)) != SCARD_S_SUCCESS)
|
||||
{
|
||||
// We can not connect to this device, we will just ignore it
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Configure I/O settings for card communication
|
||||
dsa.ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST);
|
||||
|
||||
// Retrieve the current firmware version
|
||||
pcFirmware = dev_acr122_firmware((dev_info*)&dsa);
|
||||
if (strstr(pcFirmware,FIRMWARE_TEXT) != null)
|
||||
{
|
||||
// We found a occurence, test if it has the right index
|
||||
if (uiDevIndex != 0)
|
||||
{
|
||||
// Let's look for the next reader
|
||||
uiDevIndex--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Allocate memory and store the device specification
|
||||
pdsa = malloc(sizeof(dev_spec_acr122));
|
||||
*pdsa = dsa;
|
||||
|
||||
// Done, we found the reader we are looking for
|
||||
pdi = malloc(sizeof(dev_info));
|
||||
strcpy(pdi->acName,pcFirmware);
|
||||
pdi->ct = CT_PN532;
|
||||
pdi->ds = (dev_spec)pdsa;
|
||||
pdi->bActive = true;
|
||||
pdi->bCrc = true;
|
||||
pdi->bPar = true;
|
||||
pdi->ui8TxBits = 0;
|
||||
return pdi;
|
||||
}
|
||||
}
|
||||
|
||||
// Too bad, the reader could not be located;
|
||||
return INVALID_DEVICE_INFO;
|
||||
}
|
||||
|
||||
void dev_acr122_disconnect(dev_info* pdi)
|
||||
{
|
||||
dev_spec_acr122* pdsa = (dev_spec_acr122*)pdi->ds;
|
||||
SCardDisconnect(pdsa->hCard,SCARD_LEAVE_CARD);
|
||||
SCardReleaseContext(pdsa->hCtx);
|
||||
free(pdsa);
|
||||
free(pdi);
|
||||
}
|
||||
|
||||
bool dev_acr122_transceive(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen)
|
||||
{
|
||||
dev_spec_acr122* pdsa = (dev_spec_acr122*)ds;
|
||||
|
||||
// Make sure the command does not overflow the send buffer
|
||||
if (uiTxLen > ACR122_COMMAND_LEN) return false;
|
||||
|
||||
// Store the length of the command we are going to send
|
||||
abtTxBuf[4] = uiTxLen;
|
||||
|
||||
// Prepare and transmit the send buffer
|
||||
memcpy(abtTxBuf+5,pbtTx,uiTxLen);
|
||||
ulRxBufLen = sizeof(abtRxBuf);
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Tx: ");
|
||||
print_hex(abtTxBuf,uiTxLen+5);
|
||||
#endif
|
||||
|
||||
if (pdsa->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED)
|
||||
{
|
||||
if (SCardControl(pdsa->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtTxBuf,uiTxLen+5,abtRxBuf,ulRxBufLen,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false;
|
||||
} else {
|
||||
if (SCardTransmit(pdsa->hCard,&(pdsa->ioCard),abtTxBuf,uiTxLen+5,null,abtRxBuf,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false;
|
||||
}
|
||||
|
||||
if (pdsa->ioCard.dwProtocol == SCARD_PROTOCOL_T0)
|
||||
{
|
||||
// Make sure we received the byte-count we expected
|
||||
if (ulRxBufLen != 2) return false;
|
||||
|
||||
// Check if the operation was successful, so an answer is available
|
||||
if (*abtRxBuf == SCARD_OPERATION_ERROR) return false;
|
||||
|
||||
// Retrieve the response bytes
|
||||
abtRxCmd[4] = abtRxBuf[1];
|
||||
ulRxBufLen = sizeof(abtRxBuf);
|
||||
if (SCardTransmit(pdsa->hCard,&(pdsa->ioCard),abtRxCmd,uiRxCmdLen,null,abtRxBuf,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false;
|
||||
}
|
||||
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Rx: ");
|
||||
print_hex(abtRxBuf,ulRxBufLen);
|
||||
#endif
|
||||
|
||||
// When the answer should be ignored, just return a succesful result
|
||||
if (pbtRx == null || puiRxLen == null) return true;
|
||||
|
||||
// Make sure we have an emulated answer that fits the return buffer
|
||||
if (ulRxBufLen < 4 || (ulRxBufLen-4) > *puiRxLen) return false;
|
||||
// Wipe out the 4 APDU emulation bytes: D5 4B .. .. .. 90 00
|
||||
*puiRxLen = ulRxBufLen-4;
|
||||
memcpy(pbtRx,abtRxBuf+2,*puiRxLen);
|
||||
|
||||
// Transmission went successful
|
||||
return true;
|
||||
}
|
||||
|
||||
char* dev_acr122_firmware(const dev_spec ds)
|
||||
{
|
||||
ui32 uiResult;
|
||||
|
||||
dev_spec_acr122* pdsa = (dev_spec_acr122*)ds;
|
||||
static char abtFw[11];
|
||||
ulong ulFwLen = sizeof(abtFw);
|
||||
memset(abtFw,0x00,ulFwLen);
|
||||
if (pdsa->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED)
|
||||
{
|
||||
uiResult = SCardControl(pdsa->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtGetFw,sizeof(abtGetFw),abtFw,ulFwLen,(void*)&ulFwLen);
|
||||
} else {
|
||||
uiResult = SCardTransmit(pdsa->hCard,&(pdsa->ioCard),abtGetFw,sizeof(abtGetFw),null,(byte*)abtFw,(void*)&ulFwLen);
|
||||
}
|
||||
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
if (uiResult != SCARD_S_SUCCESS)
|
||||
{
|
||||
printf("No ACR122 firmware received, Error: %08x\n",uiResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
return abtFw;
|
||||
}
|
||||
|
||||
bool dev_acr122_led_red(const dev_spec ds, bool bOn)
|
||||
{
|
||||
dev_spec_acr122* pdsa = (dev_spec_acr122*)ds;
|
||||
byte abtBuf[2];
|
||||
ulong ulBufLen = sizeof(abtBuf);
|
||||
if (pdsa->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED)
|
||||
{
|
||||
return (SCardControl(pdsa->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtLed,sizeof(abtLed),abtBuf,ulBufLen,(void*)&ulBufLen) == SCARD_S_SUCCESS);
|
||||
} else {
|
||||
return (SCardTransmit(pdsa->hCard,&(pdsa->ioCard),abtLed,sizeof(abtLed),null,(byte*)abtBuf,(void*)&ulBufLen) == SCARD_S_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
39
dev_acr122.h
Normal file
39
dev_acr122.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
|
||||
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 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 General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _LIBNFC_DEV_ACR122_H_
|
||||
#define _LIBNFC_DEV_ACR122_H_
|
||||
|
||||
#include "defines.h"
|
||||
#include "types.h"
|
||||
|
||||
// Functions used by developer to handle connection to this device
|
||||
dev_info* dev_acr122_connect(const ui32 uiIndex);
|
||||
void dev_acr122_disconnect(dev_info* pdi);
|
||||
|
||||
// Callback function used by libnfc to transmit commands to the PN53X chip
|
||||
bool dev_acr122_transceive(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen);
|
||||
|
||||
// Various additional features this device supports
|
||||
char* dev_acr122_firmware(const dev_spec ds);
|
||||
bool dev_acr122_led_red(const dev_spec ds, bool bOn);
|
||||
|
||||
#endif // _LIBNFC_DEV_ACR122_H_
|
||||
|
247
dev_pn531.c
Normal file
247
dev_pn531.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
|
||||
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 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 General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Thanks to d18c7db and Okko for example code
|
||||
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#include <usb.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "dev_pn531.h"
|
||||
#include "bitutils.h"
|
||||
|
||||
#define BUFFER_LENGTH 256
|
||||
#define USB_TIMEOUT 30000
|
||||
static char buffer[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
||||
|
||||
typedef struct {
|
||||
usb_dev_handle* pudh;
|
||||
ui32 uiEndPointIn;
|
||||
ui32 uiEndPointOut;
|
||||
} dev_spec_pn531;
|
||||
|
||||
// Find transfer endpoints for bulk transfers
|
||||
void get_end_points(struct usb_device *dev, dev_spec_pn531* pdsp)
|
||||
{
|
||||
ui32 uiIndex;
|
||||
ui32 uiEndPoint;
|
||||
struct usb_interface_descriptor* puid = dev->config->interface->altsetting;
|
||||
|
||||
// 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
|
||||
for(uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++)
|
||||
{
|
||||
// Only accept bulk transfer endpoints (ignore interrupt endpoints)
|
||||
if(puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK) continue;
|
||||
|
||||
// Copy the endpoint to a local var, makes it more readable code
|
||||
uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress;
|
||||
|
||||
// Test if we dealing with a bulk IN endpoint
|
||||
if((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN)
|
||||
{
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Bulk endpoint in : 0x%02X\n", uiEndPoint);
|
||||
#endif
|
||||
pdsp->uiEndPointIn = uiEndPoint;
|
||||
}
|
||||
|
||||
// Test if we dealing with a bulk OUT endpoint
|
||||
if((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT)
|
||||
{
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Bulk endpoint in : 0x%02X\n", uiEndPoint);
|
||||
#endif
|
||||
pdsp->uiEndPointOut = uiEndPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev_info* dev_pn531_connect(const ui32 uiIndex)
|
||||
{
|
||||
int idvendor = 0x04CC;
|
||||
int idproduct = 0x0531;
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
dev_info* pdi = INVALID_DEVICE_INFO;
|
||||
dev_spec_pn531* pdsp;
|
||||
dev_spec_pn531 dsp;
|
||||
ui32 uiDevIndex;
|
||||
|
||||
dsp.uiEndPointIn = 0;
|
||||
dsp.uiEndPointOut = 0;
|
||||
dsp.pudh = null;
|
||||
|
||||
usb_init();
|
||||
if (usb_find_busses() < 0) return INVALID_DEVICE_INFO;
|
||||
if (usb_find_devices() < 0) return INVALID_DEVICE_INFO;
|
||||
|
||||
// Initialize the device index we are seaching for
|
||||
uiDevIndex = uiIndex;
|
||||
|
||||
for (bus = usb_get_busses(); bus; bus = bus->next)
|
||||
{
|
||||
for (dev = bus->devices; dev; dev = dev->next)
|
||||
{
|
||||
if (idvendor==dev->descriptor.idVendor && idproduct==dev->descriptor.idProduct)
|
||||
{
|
||||
// Make sure there are 2 endpoints available
|
||||
if (dev->config->interface->altsetting->bNumEndpoints < 2) return pdi;
|
||||
|
||||
// Test if we are looking for this device according to the current index
|
||||
if (uiDevIndex != 0)
|
||||
{
|
||||
// Nope, we maybe want the next one, let's try to find another
|
||||
uiDevIndex--;
|
||||
continue;
|
||||
}
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Found PN531 device\n");
|
||||
#endif
|
||||
|
||||
// Open the PN531 USB device
|
||||
dsp.pudh = usb_open(dev);
|
||||
|
||||
get_end_points(dev,&dsp);
|
||||
if(usb_set_configuration(dsp.pudh,1) < 0)
|
||||
{
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Setting config failed\n");
|
||||
#endif
|
||||
usb_close(dsp.pudh);
|
||||
return INVALID_DEVICE_INFO;
|
||||
}
|
||||
|
||||
if(usb_claim_interface(dsp.pudh,0) < 0)
|
||||
{
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Can't claim interface\n");
|
||||
#endif
|
||||
usb_close(dsp.pudh);
|
||||
return INVALID_DEVICE_INFO;
|
||||
}
|
||||
// Allocate memory for the device info and specification, fill it and return the info
|
||||
pdsp = malloc(sizeof(dev_spec_pn531));
|
||||
*pdsp = dsp;
|
||||
pdi = malloc(sizeof(dev_info));
|
||||
strcpy(pdi->acName,"PN531USB");
|
||||
pdi->ct = CT_PN531;
|
||||
pdi->ds = (dev_spec)pdsp;
|
||||
pdi->bActive = true;
|
||||
pdi->bCrc = true;
|
||||
pdi->bPar = true;
|
||||
pdi->ui8TxBits = 0;
|
||||
return pdi;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pdi;
|
||||
}
|
||||
|
||||
void dev_pn531_disconnect(dev_info* pdi)
|
||||
{
|
||||
dev_spec_pn531* pdsp = (dev_spec_pn531*)pdi->ds;
|
||||
usb_release_interface(pdsp->pudh,0);
|
||||
usb_close(pdsp->pudh);
|
||||
free(pdi->ds);
|
||||
free(pdi);
|
||||
}
|
||||
|
||||
bool dev_pn531_transceive(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen)
|
||||
{
|
||||
ui32 uiPos = 0;
|
||||
int ret = 0;
|
||||
char buf[BUFFER_LENGTH];
|
||||
dev_spec_pn531* pdsp = (dev_spec_pn531*)ds;
|
||||
|
||||
// Packet length = data length (len) + checksum (1) + end of stream marker (1)
|
||||
buffer[3] = uiTxLen;
|
||||
// Packet length checksum
|
||||
buffer[4] = BUFFER_LENGTH - buffer[3];
|
||||
// Copy the PN53X command into the packet buffer
|
||||
memmove(buffer+5,pbtTx,uiTxLen);
|
||||
|
||||
// Calculate data payload checksum
|
||||
buffer[uiTxLen+5] = 0;
|
||||
for(uiPos=0; uiPos < uiTxLen; uiPos++)
|
||||
{
|
||||
buffer[uiTxLen+5] -= buffer[uiPos+5];
|
||||
}
|
||||
|
||||
// End of stream marker
|
||||
buffer[uiTxLen+6] = 0;
|
||||
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Tx: ");
|
||||
print_hex((byte*)buffer,uiTxLen+7);
|
||||
#endif
|
||||
|
||||
ret = usb_bulk_write(pdsp->pudh, pdsp->uiEndPointOut, buffer, uiTxLen+7, USB_TIMEOUT);
|
||||
if( ret < 0 )
|
||||
{
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("usb_bulk_write failed with error %d\n", ret);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = usb_bulk_read(pdsp->pudh, pdsp->uiEndPointIn, buf, BUFFER_LENGTH, USB_TIMEOUT);
|
||||
if( ret < 0 )
|
||||
{
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf( "usb_bulk_read failed with error %d\n", ret);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Rx: ");
|
||||
print_hex((byte*)buf,ret);
|
||||
#endif
|
||||
|
||||
if( ret == 6 )
|
||||
{
|
||||
ret = usb_bulk_read(pdsp->pudh, pdsp->uiEndPointIn, buf, BUFFER_LENGTH, USB_TIMEOUT);
|
||||
if( ret < 0 )
|
||||
{
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("usb_bulk_read failed with error %d\n", ret);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _LIBNFC_VERBOSE_
|
||||
printf("Rx: ");
|
||||
print_hex((byte*)buf,ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
// When the answer should be ignored, just return a succesful result
|
||||
if(pbtRx == null || puiRxLen == null) return true;
|
||||
|
||||
// Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
|
||||
if(ret < 9) return false;
|
||||
|
||||
// Remove the preceding and appending bytes 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
|
||||
*puiRxLen = ret - 7 - 2;
|
||||
memcpy( pbtRx, buf + 7, *puiRxLen);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -18,19 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
*/
|
||||
|
||||
#ifndef _LIBNFC_ACR122_H_
|
||||
#define _LIBNFC_ACR122_H_
|
||||
#ifndef _LIBNFC_DEV_PN531_H_
|
||||
#define _LIBNFC_DEV_PN531_H_
|
||||
|
||||
#include "defines.h"
|
||||
#include "types.h"
|
||||
|
||||
dev_id acr122_connect(const ui32 uiDeviceIndex);
|
||||
void acr122_disconnect(const dev_id di);
|
||||
bool acr122_transceive(const dev_id di, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen);
|
||||
bool acr122_transceive_(const dev_id di, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen);
|
||||
// Functions used by developer to handle connection to this device
|
||||
dev_info* dev_pn531_connect(const ui32 uiIndex);
|
||||
void dev_pn531_disconnect(dev_info* pdi);
|
||||
|
||||
char* acr122_firmware(const dev_id di);
|
||||
bool acr122_led_red(const dev_id di, bool bOn);
|
||||
// Callback function used by libnfc to transmit commands to the PN53X chip
|
||||
bool dev_pn531_transceive(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen);
|
||||
|
||||
#endif // _LIBNFC_ACR122_H_
|
||||
#endif // _LIBNFC_DEV_PN531_H_
|
||||
|
225
mfread.c
225
mfread.c
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
|
||||
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 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 General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libnfc.h"
|
||||
#include "mifaretag.h"
|
||||
|
||||
static byte abtRecv[MAX_FRAME_LEN];
|
||||
static ui32 uiRecvLen;
|
||||
static dev_id di;
|
||||
static MifareParam mp;
|
||||
static MifareTag mtKeys;
|
||||
static MifareTag mtDump;
|
||||
|
||||
bool is_trailer_block(ui32 uiBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiBlock < 128) return ((uiBlock+1)%4 == 0); else return ((uiBlock+1)%16 == 0);
|
||||
}
|
||||
|
||||
ui32 get_trailer_block(ui32 uiSector)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiSector<32)
|
||||
{
|
||||
return (uiSector*4)+3;
|
||||
} else {
|
||||
return 128+((uiSector-32)*16)+15;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
bool b4K;
|
||||
bool bKeyA;
|
||||
byte* pbtUID;
|
||||
bool bFailure;
|
||||
i32 iBlock;
|
||||
ui32 uiBlocks;
|
||||
FILE* pfKeys;
|
||||
FILE* pfDump;
|
||||
MifareCmd mc;
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
printf("mfread <a|b> <keys.mfd> <dump.mfd>\n");
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bKeyA = (*(argv[1]) == 'a');
|
||||
|
||||
pfKeys = fopen(argv[2],"rb");
|
||||
if (pfKeys == null)
|
||||
{
|
||||
printf("Could not open file: %s\n",argv[2]);
|
||||
return 1;
|
||||
}
|
||||
fread(&mtKeys,1,sizeof(mtKeys),pfKeys);
|
||||
fclose(pfKeys);
|
||||
|
||||
pfDump = fopen(argv[3],"wb");
|
||||
if (pfKeys == null)
|
||||
{
|
||||
printf("Could not open file: %s\n",argv[3]);
|
||||
return 1;
|
||||
}
|
||||
memset(&mtDump,0x00,sizeof(mtDump));
|
||||
printf("Succesful opened MIFARE dump files\n");
|
||||
|
||||
// Try to open the NFC reader
|
||||
di = acr122_connect(0);
|
||||
if (di == INVALID_DEVICE_ID)
|
||||
{
|
||||
printf("Error connecting NFC reader\n");
|
||||
return 1;
|
||||
}
|
||||
nfc_reader_init(di);
|
||||
// Let the reader only try once to find a tag
|
||||
nfc_configure_list_passive_infinite(di,false);
|
||||
|
||||
// Drop the field so the tag will be reset
|
||||
nfc_configure_field(di,false);
|
||||
|
||||
// Configure the communication channel
|
||||
nfc_configure_handle_crc(di,true);
|
||||
nfc_configure_handle_parity(di,true);
|
||||
printf("Connected to NFC reader\n");
|
||||
|
||||
// MIFARE Classic tag info = ( tag_count[1], tag_nr[1], ATQA[2], SAK[1], uid_len[1], UID[uid_len] )
|
||||
uiRecvLen = MAX_FRAME_LEN;
|
||||
if (!nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen))
|
||||
{
|
||||
printf("Error: no tag was found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test if we are dealing with a MIFARE compatible tag
|
||||
if ((abtRecv[4] & 0x08) == 0)
|
||||
{
|
||||
printf("Error: tag is not a MIFARE Classic card\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the info from the key dump
|
||||
b4K = (mtKeys.blContent[0].bm.abtATQA[0] == 0x02);
|
||||
pbtUID = mtKeys.blContent[0].bm.abtUID;
|
||||
|
||||
// Compare if key dump UID is the same as the current tag UID
|
||||
if (memcmp(abtRecv+6,pbtUID,4) != 0)
|
||||
{
|
||||
printf("Expected MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID));
|
||||
}
|
||||
|
||||
// Get the info from the current tag
|
||||
pbtUID = abtRecv+6;
|
||||
b4K = (abtRecv[3] == 0x02);
|
||||
printf("Found MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID));
|
||||
|
||||
uiBlocks = (b4K)?0xff:0x3f;
|
||||
bFailure = false;
|
||||
printf("Reading out %d blocks |",uiBlocks+1);
|
||||
|
||||
// Read the card from end to begin
|
||||
for (iBlock=uiBlocks; iBlock>=0; iBlock--)
|
||||
{
|
||||
// Authenticate everytime we reach a trailer block
|
||||
if (is_trailer_block(iBlock))
|
||||
{
|
||||
// Show if the readout went well
|
||||
if (bFailure)
|
||||
{
|
||||
printf("x");
|
||||
// When a failure occured we need to redo the anti-collision
|
||||
if (!nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen))
|
||||
{
|
||||
printf("!\nError: tag was removed\n");
|
||||
return 1;
|
||||
}
|
||||
bFailure = false;
|
||||
} else {
|
||||
// Skip this the first time, bFailure it means nothing (yet)
|
||||
if (iBlock != uiBlocks)
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
// Set the authentication information (uid)
|
||||
memcpy(mp.mpa.abtUid,abtRecv+6,4);
|
||||
|
||||
// Determin if we should use the a or the b key
|
||||
if (bKeyA)
|
||||
{
|
||||
mc = MC_AUTH_A;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.blContent[iBlock].bt.abtKeyA,6);
|
||||
} else {
|
||||
mc = MC_AUTH_B;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.blContent[iBlock].bt.abtKeyB,6);
|
||||
}
|
||||
|
||||
// Try to authenticate for the current sector
|
||||
if (!nfc_reader_mifare_cmd(di,MC_AUTH_A,iBlock,&mp))
|
||||
{
|
||||
printf("!\nError: authentication failed for block %02x\n",iBlock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Try to read out the trailer
|
||||
if (nfc_reader_mifare_cmd(di,MC_READ,iBlock,&mp))
|
||||
{
|
||||
// Copy the keys over from our key dump and store the retrieved access bits
|
||||
memcpy(mtDump.blContent[iBlock].bd.abtContent,mtKeys.blContent[iBlock].bt.abtKeyA,6);
|
||||
memcpy(mtDump.blContent[iBlock].bt.abtAccessBits,mp.mpd.abtData+6,4);
|
||||
memcpy(mtDump.blContent[iBlock].bd.abtContent+10,mtKeys.blContent[iBlock].bt.abtKeyB,6);
|
||||
}
|
||||
} else {
|
||||
// Make sure a earlier readout did not fail
|
||||
if (!bFailure)
|
||||
{
|
||||
// Try to read out the data block
|
||||
if (nfc_reader_mifare_cmd(di,MC_READ,iBlock,&mp))
|
||||
{
|
||||
memcpy(mtDump.blContent[iBlock].bd.abtContent,mp.mpd.abtData,16);
|
||||
} else {
|
||||
bFailure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("%c|\n",(bFailure)?'x':'.');
|
||||
fflush(stdout);
|
||||
|
||||
printf("Writing dump to file: %s\n",argv[3]);
|
||||
fflush(stdout);
|
||||
fwrite(&mtDump,1,sizeof(mtDump),pfDump);
|
||||
fclose(pfKeys);
|
||||
|
||||
printf("Done, all data is dumped!\n");
|
||||
|
||||
return 0;
|
||||
}
|
374
mftool.c
Normal file
374
mftool.c
Normal file
|
@ -0,0 +1,374 @@
|
|||
/*
|
||||
|
||||
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 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 General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libnfc.h"
|
||||
#include "mifaretag.h"
|
||||
|
||||
static dev_info* pdi;
|
||||
static tag_info ti;
|
||||
static mifare_param mp;
|
||||
static mifare_tag mtKeys;
|
||||
static mifare_tag mtDump;
|
||||
static bool bUseKeyA;
|
||||
static ui32 uiBlocks;
|
||||
|
||||
bool is_first_block(ui32 uiBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiBlock < 128) return ((uiBlock)%4 == 0); else return ((uiBlock)%16 == 0);
|
||||
}
|
||||
|
||||
bool is_trailer_block(ui32 uiBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiBlock < 128) return ((uiBlock+1)%4 == 0); else return ((uiBlock+1)%16 == 0);
|
||||
}
|
||||
|
||||
ui32 get_trailer_block(ui32 uiFirstBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiFirstBlock<128) return uiFirstBlock+3; else return uiFirstBlock+15;
|
||||
}
|
||||
|
||||
bool read_card()
|
||||
{
|
||||
i32 iBlock;
|
||||
mifare_cmd mc;
|
||||
bool bFailure = false;
|
||||
|
||||
printf("Reading out %d blocks |",uiBlocks+1);
|
||||
|
||||
// Read the card from end to begin
|
||||
for (iBlock=uiBlocks; iBlock>=0; iBlock--)
|
||||
{
|
||||
// Authenticate everytime we reach a trailer block
|
||||
if (is_trailer_block(iBlock))
|
||||
{
|
||||
// Show if the readout went well
|
||||
if (bFailure)
|
||||
{
|
||||
printf("x");
|
||||
// When a failure occured we need to redo the anti-collision
|
||||
if (!nfc_reader_select(pdi,IM_ISO14443A_106,null,null,&ti))
|
||||
{
|
||||
printf("!\nError: tag was removed\n");
|
||||
return 1;
|
||||
}
|
||||
bFailure = false;
|
||||
} else {
|
||||
// Skip this the first time, bFailure it means nothing (yet)
|
||||
if (iBlock != uiBlocks)
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
// Set the authentication information (uid)
|
||||
memcpy(mp.mpa.abtUid,ti.tia.abtUid,4);
|
||||
|
||||
// Determin if we should use the a or the b key
|
||||
if (bUseKeyA)
|
||||
{
|
||||
mc = MC_AUTH_A;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.amb[iBlock].mbt.abtKeyA,6);
|
||||
} else {
|
||||
mc = MC_AUTH_B;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.amb[iBlock].mbt.abtKeyB,6);
|
||||
}
|
||||
|
||||
// Try to authenticate for the current sector
|
||||
if (!nfc_reader_mifare_cmd(pdi,MC_AUTH_A,iBlock,&mp))
|
||||
{
|
||||
printf("!\nError: authentication failed for block %02x\n",iBlock);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to read out the trailer
|
||||
if (nfc_reader_mifare_cmd(pdi,MC_READ,iBlock,&mp))
|
||||
{
|
||||
// Copy the keys over from our key dump and store the retrieved access bits
|
||||
memcpy(mtDump.amb[iBlock].mbt.abtKeyA,mtKeys.amb[iBlock].mbt.abtKeyA,6);
|
||||
memcpy(mtDump.amb[iBlock].mbt.abtAccessBits,mp.mpd.abtData+6,4);
|
||||
memcpy(mtDump.amb[iBlock].mbt.abtKeyB,mtKeys.amb[iBlock].mbt.abtKeyB,6);
|
||||
}
|
||||
} else {
|
||||
// Make sure a earlier readout did not fail
|
||||
if (!bFailure)
|
||||
{
|
||||
// Try to read out the data block
|
||||
if (nfc_reader_mifare_cmd(pdi,MC_READ,iBlock,&mp))
|
||||
{
|
||||
memcpy(mtDump.amb[iBlock].mbd.abtData,mp.mpd.abtData,16);
|
||||
} else {
|
||||
bFailure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("%c|\n",(bFailure)?'x':'.');
|
||||
fflush(stdout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_card()
|
||||
{
|
||||
ui32 uiBlock;
|
||||
ui32 uiTrailerBlock;
|
||||
bool bFailure = false;
|
||||
mifare_cmd mc;
|
||||
|
||||
printf("Writing %d blocks |",uiBlocks+1);
|
||||
|
||||
// Write the card from begin to end;
|
||||
for (uiBlock=0; uiBlock<=uiBlocks; uiBlock++)
|
||||
{
|
||||
// Authenticate everytime we reach the first sector of a new block
|
||||
if (is_first_block(uiBlock))
|
||||
{
|
||||
// Show if the readout went well
|
||||
if (bFailure)
|
||||
{
|
||||
printf("x");
|
||||
// When a failure occured we need to redo the anti-collision
|
||||
if (!nfc_reader_select(pdi,IM_ISO14443A_106,null,null,&ti))
|
||||
{
|
||||
printf("!\nError: tag was removed\n");
|
||||
return false;
|
||||
}
|
||||
bFailure = false;
|
||||
} else {
|
||||
// Skip this the first time, bFailure it means nothing (yet)
|
||||
if (uiBlock != 0)
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
// Locate the trailer (with the keys) used for this sector
|
||||
uiTrailerBlock = get_trailer_block(uiBlock);
|
||||
|
||||
// Set the authentication information (uid)
|
||||
memcpy(mp.mpa.abtUid,ti.tia.abtUid,4);
|
||||
|
||||
// Determin if we should use the a or the b key
|
||||
if (bUseKeyA)
|
||||
{
|
||||
mc = MC_AUTH_A;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.amb[uiTrailerBlock].mbt.abtKeyA,6);
|
||||
} else {
|
||||
mc = MC_AUTH_B;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.amb[uiTrailerBlock].mbt.abtKeyB,6);
|
||||
}
|
||||
|
||||
// Try to authenticate for the current sector
|
||||
if (!nfc_reader_mifare_cmd(pdi,mc,uiBlock,&mp))
|
||||
{
|
||||
printf("!\nError: authentication failed for block %02x\n",uiBlock);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_trailer_block(uiBlock))
|
||||
{
|
||||
// Copy the keys over from our key dump and store the retrieved access bits
|
||||
memcpy(mp.mpd.abtData,mtDump.amb[uiBlock].mbt.abtKeyA,6);
|
||||
memcpy(mp.mpd.abtData+6,mtDump.amb[uiBlock].mbt.abtAccessBits,4);
|
||||
memcpy(mp.mpd.abtData+10,mtDump.amb[uiBlock].mbt.abtKeyB,6);
|
||||
|
||||
// Try to write the trailer
|
||||
nfc_reader_mifare_cmd(pdi,MC_WRITE,uiBlock,&mp);
|
||||
|
||||
} else {
|
||||
|
||||
// The first block 0x00 is read only, skip this
|
||||
if (uiBlock == 0) continue;
|
||||
|
||||
// Make sure a earlier write did not fail
|
||||
if (!bFailure)
|
||||
{
|
||||
// Try to write the data block
|
||||
memcpy(mp.mpd.abtData,mtDump.amb[uiBlock].mbd.abtData,16);
|
||||
if (!nfc_reader_mifare_cmd(pdi,MC_WRITE,uiBlock,&mp)) bFailure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("%c|\n",(bFailure)?'x':'.');
|
||||
fflush(stdout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
bool b4K;
|
||||
bool bReadAction;
|
||||
byte* pbtUID;
|
||||
FILE* pfKeys;
|
||||
FILE* pfDump;
|
||||
|
||||
if (argc < 5)
|
||||
{
|
||||
printf("\n");
|
||||
printf("mftool <r|w> <a|b> <keys.mfd> <dump.mfd>\n");
|
||||
printf("\n");
|
||||
printf("<r|w> - Perform (read from) or (write to) card\n");
|
||||
printf("<a|b> - Use A or B keys to for action\n");
|
||||
printf("<keys.mfd> - Mifare-dump that contain the keys\n");
|
||||
printf("<dump.mfd> - Used to write (card to file) or (file to card)\n");
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\nChecking arguments and settings\n");
|
||||
|
||||
bReadAction = (tolower(*(argv[1])) == 'r');
|
||||
bUseKeyA = (tolower(*(argv[2])) == 'a');
|
||||
|
||||
pfKeys = fopen(argv[3],"rb");
|
||||
if (pfKeys == null)
|
||||
{
|
||||
printf("Could not open file: %s\n",argv[3]);
|
||||
return 1;
|
||||
}
|
||||
if (fread(&mtKeys,1,sizeof(mtKeys),pfKeys) != sizeof(mtKeys))
|
||||
{
|
||||
printf("Could not read from keys file: %s\n",argv[3]);
|
||||
fclose(pfKeys);
|
||||
return 1;
|
||||
}
|
||||
fclose(pfKeys);
|
||||
|
||||
if (bReadAction)
|
||||
{
|
||||
memset(&mtDump,0x00,sizeof(mtDump));
|
||||
} else {
|
||||
pfDump = fopen(argv[4],"rb");
|
||||
|
||||
if (pfDump == null)
|
||||
{
|
||||
printf("Could not open dump file: %s\n",argv[4]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fread(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump))
|
||||
{
|
||||
printf("Could not read from dump file: %s\n",argv[4]);
|
||||
fclose(pfDump);
|
||||
return 1;
|
||||
}
|
||||
fclose(pfDump);
|
||||
}
|
||||
printf("Succesful opened MIFARE the required files\n");
|
||||
|
||||
// Try to open the NFC reader
|
||||
pdi = nfc_connect();
|
||||
if (pdi == INVALID_DEVICE_INFO)
|
||||
{
|
||||
printf("Error connecting NFC reader\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
nfc_reader_init(pdi);
|
||||
|
||||
// Drop the field for a while
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);
|
||||
|
||||
// Let the reader only try once to find a tag
|
||||
nfc_configure(pdi,DCO_INFINITE_SELECT,false);
|
||||
nfc_configure(pdi,DCO_HANDLE_CRC,true);
|
||||
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
|
||||
|
||||
// Enable field so more power consuming cards can power themselves up
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);
|
||||
|
||||
printf("Connected to NFC reader: %s\n",pdi->acName);
|
||||
|
||||
// Try to find a MIFARE Classic tag
|
||||
if (!nfc_reader_select(pdi,IM_ISO14443A_106,null,null,&ti))
|
||||
{
|
||||
printf("Error: no tag was found\n");
|
||||
nfc_disconnect(pdi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test if we are dealing with a MIFARE compatible tag
|
||||
if ((ti.tia.btSak & 0x08) == 0)
|
||||
{
|
||||
printf("Error: tag is not a MIFARE Classic card\n");
|
||||
nfc_disconnect(pdi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the info from the key dump
|
||||
b4K = (mtKeys.amb[0].mbm.abtATQA[1] == 0x02);
|
||||
pbtUID = mtKeys.amb[0].mbm.abtUID;
|
||||
|
||||
// Compare if key dump UID is the same as the current tag UID
|
||||
if (memcmp(ti.tia.abtUid,pbtUID,4) != 0)
|
||||
{
|
||||
printf("Expected MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID));
|
||||
}
|
||||
|
||||
// Get the info from the current tag
|
||||
pbtUID = ti.tia.abtUid;
|
||||
b4K = (ti.tia.abtAtqa[1] == 0x02);
|
||||
printf("Found MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID));
|
||||
|
||||
uiBlocks = (b4K)?0xff:0x3f;
|
||||
|
||||
if (bReadAction)
|
||||
{
|
||||
if (read_card())
|
||||
{
|
||||
printf("Writing data to file: %s\n",argv[4]);
|
||||
fflush(stdout);
|
||||
pfDump = fopen(argv[4],"wb");
|
||||
if (pfKeys == null)
|
||||
{
|
||||
printf("Could not open file: %s\n",argv[4]);
|
||||
return 1;
|
||||
}
|
||||
if (fwrite(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump))
|
||||
{
|
||||
printf("Could not write to file: %s\n",argv[4]);
|
||||
return 1;
|
||||
}
|
||||
fclose(pfDump);
|
||||
printf("Done, all bytes dumped to file!\n");
|
||||
}
|
||||
} else {
|
||||
if (write_card())
|
||||
{
|
||||
printf("Done, all data is written to the card!\n");
|
||||
}
|
||||
}
|
||||
|
||||
nfc_disconnect(pdi);
|
||||
|
||||
return 0;
|
||||
}
|
232
mfwrite.c
232
mfwrite.c
|
@ -1,232 +0,0 @@
|
|||
/*
|
||||
|
||||
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 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 General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libnfc.h"
|
||||
#include "mifaretag.h"
|
||||
|
||||
static byte abtRecv[MAX_FRAME_LEN];
|
||||
static ui32 uiRecvLen;
|
||||
static dev_id di;
|
||||
static MifareParam mp;
|
||||
static MifareTag mtKeys;
|
||||
static MifareTag mtDump;
|
||||
|
||||
bool is_first_block(ui32 uiBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiBlock < 128) return ((uiBlock)%4 == 0); else return ((uiBlock)%16 == 0);
|
||||
}
|
||||
|
||||
bool is_trailer_block(ui32 uiBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiBlock < 128) return ((uiBlock+1)%4 == 0); else return ((uiBlock+1)%16 == 0);
|
||||
}
|
||||
|
||||
ui32 get_trailer_block(ui32 uiFirstBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiFirstBlock<128) return uiFirstBlock+3; else return uiFirstBlock+15;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
bool b4K;
|
||||
bool bKeyA;
|
||||
byte* pbtUID;
|
||||
bool bFailure;
|
||||
ui32 uiBlock;
|
||||
ui32 uiBlocks;
|
||||
ui32 uiTrailerBlock;
|
||||
FILE* pfKeys;
|
||||
FILE* pfDump;
|
||||
MifareCmd mc;
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
printf("mfwrite <a|b> <keys.mfd> <dump.mfd>\n");
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bKeyA = (*(argv[1]) == 'a');
|
||||
|
||||
pfKeys = fopen(argv[2],"rb");
|
||||
if (pfKeys == null)
|
||||
{
|
||||
printf("Could not open file: %s\n",argv[2]);
|
||||
return 1;
|
||||
}
|
||||
fread(&mtKeys,1,sizeof(mtKeys),pfKeys);
|
||||
fclose(pfKeys);
|
||||
|
||||
pfDump = fopen(argv[3],"rb");
|
||||
if (pfKeys == null)
|
||||
{
|
||||
printf("Could not open file: %s\n",argv[3]);
|
||||
return 1;
|
||||
}
|
||||
fread(&mtDump,1,sizeof(mtDump),pfDump);
|
||||
fclose(pfDump);
|
||||
printf("Succesful opened MIFARE dump files\n");
|
||||
|
||||
// Try to open the NFC reader
|
||||
di = acr122_connect(0);
|
||||
if (di == INVALID_DEVICE_ID)
|
||||
{
|
||||
printf("Error connecting NFC reader\n");
|
||||
return 1;
|
||||
}
|
||||
nfc_reader_init(di);
|
||||
// Let the reader only try once to find a tag
|
||||
nfc_configure_list_passive_infinite(di,false);
|
||||
|
||||
// Drop the field so the tag will be reset
|
||||
nfc_configure_field(di,false);
|
||||
|
||||
// Configure the communication channel
|
||||
nfc_configure_handle_crc(di,true);
|
||||
nfc_configure_handle_parity(di,true);
|
||||
printf("Connected to NFC reader\n");
|
||||
|
||||
// MIFARE Classic tag info = ( tag_count[1], tag_nr[1], ATQA[2], SAK[1], uid_len[1], UID[uid_len] )
|
||||
uiRecvLen = MAX_FRAME_LEN;
|
||||
if (!nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen))
|
||||
{
|
||||
printf("Error: no tag was found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test if we are dealing with a MIFARE compatible tag
|
||||
if ((abtRecv[4] & 0x08) == 0)
|
||||
{
|
||||
printf("Error: tag is not a MIFARE Classic card\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the info from the key dump
|
||||
b4K = (mtKeys.blContent[0].bm.abtATQA[0] == 0x02);
|
||||
pbtUID = mtKeys.blContent[0].bm.abtUID;
|
||||
|
||||
// Compare if key dump UID is the same as the current tag UID
|
||||
if (memcmp(abtRecv+6,pbtUID,4) != 0)
|
||||
{
|
||||
printf("Expected MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID));
|
||||
}
|
||||
|
||||
// Get the info from the current tag
|
||||
pbtUID = abtRecv+6;
|
||||
b4K = (abtRecv[3] == 0x02);
|
||||
printf("Found MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID));
|
||||
|
||||
uiBlocks = (b4K)?0xff:0x3f;
|
||||
bFailure = false;
|
||||
printf("Writing %d blocks |",uiBlocks+1);
|
||||
|
||||
// Write the card from begin to end;
|
||||
for (uiBlock=0; uiBlock<=uiBlocks; uiBlock++)
|
||||
{
|
||||
// Authenticate everytime we reach the first sector of a new block
|
||||
if (is_first_block(uiBlock))
|
||||
{
|
||||
// Show if the readout went well
|
||||
if (bFailure)
|
||||
{
|
||||
printf("x");
|
||||
// When a failure occured we need to redo the anti-collision
|
||||
if (!nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen))
|
||||
{
|
||||
printf("!\nError: tag was removed\n");
|
||||
return 1;
|
||||
}
|
||||
bFailure = false;
|
||||
} else {
|
||||
// Skip this the first time, bFailure it means nothing (yet)
|
||||
if (uiBlock != 0)
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
// Locate the trailer (with the keys) used for this sector
|
||||
uiTrailerBlock = get_trailer_block(uiBlock);
|
||||
|
||||
// Set the authentication information (uid)
|
||||
memcpy(mp.mpa.abtUid,abtRecv+6,4);
|
||||
|
||||
// Determin if we should use the a or the b key
|
||||
if (bKeyA)
|
||||
{
|
||||
mc = MC_AUTH_A;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.blContent[uiTrailerBlock].bt.abtKeyA,6);
|
||||
} else {
|
||||
mc = MC_AUTH_B;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.blContent[uiTrailerBlock].bt.abtKeyB,6);
|
||||
}
|
||||
|
||||
// Try to authenticate for the current sector
|
||||
if (!nfc_reader_mifare_cmd(di,mc,uiBlock,&mp))
|
||||
{
|
||||
printf("!\nError: authentication failed for block %02x\n",uiBlock);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_trailer_block(uiBlock))
|
||||
{
|
||||
// Copy the keys over from our key dump and store the retrieved access bits
|
||||
memcpy(mp.mpd.abtData,mtDump.blContent[uiBlock].bt.abtKeyA,6);
|
||||
memcpy(mp.mpd.abtData+6,mtDump.blContent[uiBlock].bt.abtAccessBits,4);
|
||||
memcpy(mp.mpd.abtData+10,mtDump.blContent[uiBlock].bt.abtKeyB,6);
|
||||
|
||||
// Try to write the trailer
|
||||
nfc_reader_mifare_cmd(di,MC_WRITE,uiBlock,&mp);
|
||||
|
||||
} else {
|
||||
|
||||
// The first block 0x00 is read only, skip this
|
||||
if (uiBlock == 0) continue;
|
||||
|
||||
// Make sure a earlier write did not fail
|
||||
if (!bFailure)
|
||||
{
|
||||
// Try to write the data block
|
||||
memcpy(mp.mpd.abtData,mtDump.blContent[uiBlock].bd.abtContent,16);
|
||||
if (!nfc_reader_mifare_cmd(di,MC_WRITE,uiBlock,&mp))
|
||||
{
|
||||
bFailure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("%c|\n",(bFailure)?'x':'.');
|
||||
fflush(stdout);
|
||||
|
||||
printf("Done, all data is written!\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="mfread"
|
||||
Version="8.00"
|
||||
Name="mftool"
|
||||
ProjectGUID="{BB0A837B-DAEF-4B3F-AF5B-9A757A97FFF3}"
|
||||
RootNamespace="mfread"
|
||||
Keyword="Win32Proj"
|
||||
|
@ -40,7 +40,7 @@
|
|||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
|
@ -116,7 +116,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
|
@ -173,7 +173,7 @@
|
|||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath="..\mfread.c"
|
||||
RelativePath="..\mftool.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
|
@ -1,185 +0,0 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="mfwrite"
|
||||
ProjectGUID="{77907F3D-BA6E-4A7F-AF9D-4F60C0A79952}"
|
||||
RootNamespace="mfwrite"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="$(ConfigurationName)/libnfc.lib"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="$(ConfigurationName)/libnfc.lib"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath="..\mfwrite.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\mifaretag.h"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
Loading…
Reference in a new issue