diff --git a/acr122.c b/acr122.c
deleted file mode 100644
index edd5525..0000000
--- a/acr122.c
+++ /dev/null
@@ -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 .
-
-*/
-
-#include
-#include
-#include
-#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 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);
-}
-
diff --git a/dev_acr122.c b/dev_acr122.c
new file mode 100644
index 0000000..b8bb640
--- /dev/null
+++ b/dev_acr122.c
@@ -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 .
+
+*/
+
+#include "defines.h"
+
+#include
+#include
+#include
+#include
+#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; uiPos2.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);
+ }
+}
+
diff --git a/dev_acr122.h b/dev_acr122.h
new file mode 100644
index 0000000..95c763d
--- /dev/null
+++ b/dev_acr122.h
@@ -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 .
+
+*/
+
+#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_
+
diff --git a/dev_pn531.c b/dev_pn531.c
new file mode 100644
index 0000000..0a8a1b8
--- /dev/null
+++ b/dev_pn531.c
@@ -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 .
+
+Thanks to d18c7db and Okko for example code
+
+*/
+
+#include "defines.h"
+
+#include
+#include
+#include
+#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;
+}
diff --git a/acr122.h b/dev_pn531.h
similarity index 60%
rename from acr122.h
rename to dev_pn531.h
index d2c7786..65419c4 100644
--- a/acr122.h
+++ b/dev_pn531.h
@@ -1,36 +1,35 @@
-/*
-
-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 .
-
-*/
-
-#ifndef _LIBNFC_ACR122_H_
-#define _LIBNFC_ACR122_H_
+/*
+
+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 .
+
+*/
+
+#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_
diff --git a/mfread.c b/mfread.c
deleted file mode 100644
index ce0ad2f..0000000
--- a/mfread.c
+++ /dev/null
@@ -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 .
-
-*/
-
-#define _CRT_SECURE_NO_WARNINGS
-
-#include
-#include
-#include
-
-#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 \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;
-}
diff --git a/mftool.c b/mftool.c
new file mode 100644
index 0000000..fb390d2
--- /dev/null
+++ b/mftool.c
@@ -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 .
+
+*/
+
+#include
+#include
+#include
+#include
+
+#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 \n");
+ printf("\n");
+ printf(" - Perform (read from) or (write to) card\n");
+ printf(" - Use A or B keys to for action\n");
+ printf(" - Mifare-dump that contain the keys\n");
+ printf(" - 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;
+}
diff --git a/mfwrite.c b/mfwrite.c
deleted file mode 100644
index 82e44af..0000000
--- a/mfwrite.c
+++ /dev/null
@@ -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 .
-
-*/
-
-#define _CRT_SECURE_NO_WARNINGS
-
-#include
-#include
-#include
-
-#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 \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;
-}
diff --git a/win32/mfread.vcproj b/win32/mftool.vcproj
similarity index 89%
rename from win32/mfread.vcproj
rename to win32/mftool.vcproj
index 4db8719..4528069 100644
--- a/win32/mfread.vcproj
+++ b/win32/mftool.vcproj
@@ -1,8 +1,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-