Merge branch 'master' into pn532_spi

This commit is contained in:
Philippe Teuwen 2013-03-03 16:10:11 +01:00
commit 2ac7963076
25 changed files with 386 additions and 197 deletions

View file

@ -1,4 +1,25 @@
Feb TBD, 2013 - 1.7.0-rc5 (release candidate) Mar 03, 2013 - 1.7.0-rc6 (release candidate)
--------------------------------------------
Fixes:
- Fix several memory leaks (nfc_drivers, libusb, config parser)
- Fix stack smash while displaying long data transmission (LOG_HEX)
- pn53x-tamashell: allow larger commands up to full extended frame
- Add missing windows file in archive (version.rc.in)
- Fix compilation warnings & potential bugs
- Fix documentation
- Fix missing malloc() calls checks
- Fix missing free() calls in some error handlers
Improvements:
- Allow to disable conffils & envvar supports on embedded platforms
- Add option to nfc-mfclassic to tolerate RW errors
Changes:
- Replace usb_set_debug() in applications by LIBNFC_LOG_LEVEL libusb group
Feb 16, 2013 - 1.7.0-rc5 (release candidate)
--------------------------------------------
Fixes: Fixes:
- Add missing sample configuration file in archive - Add missing sample configuration file in archive

View file

@ -30,7 +30,12 @@ Here are some directions to get you started:
-Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition \ -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition \
-Wbad-function-cast -Wnested-externs -Wmissing-declarations" -Wbad-function-cast -Wnested-externs -Wmissing-declarations"
$ ./configure $ ./configure
$ make clean
$ make $ make
You can chase even more issues by using clang:
$ scan-build ./configure
$ make clean
$ scan-build make
2.3 When Debianizing 2.3 When Debianizing
$ lintian *deb $ lintian *deb

View file

@ -1,7 +1,7 @@
# General init # General init
# /!\ Don't forget to update 'CMakeLists.txt' too /!\ # /!\ Don't forget to update 'CMakeLists.txt' too /!\
AC_INIT([libnfc],[1.7.0-rc5],[info@libnfc.org]) AC_INIT([libnfc],[1.7.0-rc6],[nfc-tools@googlegroups.com])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])

View file

@ -4,5 +4,5 @@ EXTRA_DIST = \
err.h \ err.h \
nfc.def \ nfc.def \
stdlib.c \ stdlib.c \
unistd.h unistd.h \
version.rc.in version.rc.in

6
debian/changelog vendored
View file

@ -1,3 +1,9 @@
libnfc (1.7.0~rc6-0) unstable; urgency=low
* New upstream release
-- yobibe <yobibe@gmail.com> Sun, 3 Mar 2013 12:42:42 +0100
libnfc (1.7.0~rc5-0) unstable; urgency=low libnfc (1.7.0~rc5-0) unstable; urgency=low
* New upstream release * New upstream release

View file

@ -3,7 +3,7 @@
AM_CPPFLAGS = $(all_includes) $(LIBNFC_CFLAGS) AM_CPPFLAGS = $(all_includes) $(LIBNFC_CFLAGS)
noinst_LTLIBRARIES = libnfcbuses.la noinst_LTLIBRARIES = libnfcbuses.la
libnfcbuses_la_SOURCES = uart.c uart.h spi.c spi.h libnfcbuses_la_SOURCES = spi.c spi.h uart.c uart.h usbbus.c usbbus.h
libnfcbuses_la_CFLAGS = -I$(top_srcdir)/libnfc libnfcbuses_la_CFLAGS = -I$(top_srcdir)/libnfc
EXTRA_DIST = uart_posix.c uart_win32.c spi_posix.c EXTRA_DIST = uart_posix.c uart_win32.c spi_posix.c

View file

@ -45,6 +45,9 @@ uart_open(const char *pcPortName)
char acPortName[255]; char acPortName[255];
struct serial_port_windows *sp = malloc(sizeof(struct serial_port_windows)); struct serial_port_windows *sp = malloc(sizeof(struct serial_port_windows));
if (sp == 0)
return INVALID_SERIAL_PORT;
// Copy the input "com?" to "\\.\COM?" format // Copy the input "com?" to "\\.\COM?" format
sprintf(acPortName, "\\\\.\\%s", pcPortName); sprintf(acPortName, "\\\\.\\%s", pcPortName);
_strupr(acPortName); _strupr(acPortName);

71
libnfc/buses/usbbus.c Normal file
View file

@ -0,0 +1,71 @@
/*-
* Public platform independent Near Field Communication (NFC) library
*
* Copyright (C) 2013, Romuald Conty
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
/**
* @file usbbus.c
* @brief libusb 0.1 driver wrapper
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include "usbbus.h"
#include "log.h"
#define LOG_CATEGORY "libnfc.buses.usbbus"
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
int usb_prepare(void)
{
static bool usb_initialized = false;
if (usb_initialized) {
return 0;
}
#ifdef ENVVARS
char *env_log_level = getenv("LIBNFC_LOG_LEVEL");
// Set libusb debug only if asked explicitely:
// LIBUSB_LOG_LEVEL=12288 (= NFC_LOG_PRIORITY_DEBUG * 2 ^ NFC_LOG_GROUP_LIBUSB)
if (env_log_level && (((atoi(env_log_level) >> (NFC_LOG_GROUP_LIBUSB * 2)) & 0x00000003) >= NFC_LOG_PRIORITY_DEBUG)) {
setenv("USB_DEBUG", "255", 1);
}
#endif
usb_init();
usb_initialized = true;
int res;
// usb_find_busses will find all of the busses on the system. Returns the
// number of changes since previous call to this function (total of new
// busses and busses removed).
if ((res = usb_find_busses()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB busses (%s)", _usb_strerror(res));
return -1;
}
// usb_find_devices will find all of the devices on each bus. This should be
// called after usb_find_busses. Returns the number of changes since the
// previous call to this function (total of new device and devices removed).
if ((res = usb_find_devices()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB devices (%s)", _usb_strerror(res));
return -1;
}
return 0;
}

46
libnfc/buses/usbbus.h Normal file
View file

@ -0,0 +1,46 @@
/*-
* Public platform independent Near Field Communication (NFC) library
*
* Copyright (C) 2013, Romuald Conty
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
/**
* @file usbbus.h
* @brief libusb 0.1 driver header
*/
#ifndef __NFC_BUS_USB_H__
# define __NFC_BUS_USB_H__
#ifndef _WIN32
// Under POSIX system, we use libusb (>= 0.1.12)
#include <usb.h>
#define USB_TIMEDOUT ETIMEDOUT
#define _usb_strerror( X ) strerror(-X)
#else
// Under Windows we use libusb-win32 (>= 1.2.5)
#include <lusb0_usb.h>
#define USB_TIMEDOUT 116
#define _usb_strerror( X ) usb_strerror()
#endif
#include <stdbool.h>
#include <string.h>
int usb_prepare(void);
#endif // __NFC_BUS_USB_H__

View file

@ -78,6 +78,8 @@ pn53x_init(struct nfc_device *pnd)
if (!CHIP_DATA(pnd)->supported_modulation_as_initiator) { if (!CHIP_DATA(pnd)->supported_modulation_as_initiator) {
CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation) * 9); CHIP_DATA(pnd)->supported_modulation_as_initiator = malloc(sizeof(nfc_modulation) * 9);
if (! CHIP_DATA(pnd)->supported_modulation_as_initiator)
return NFC_ESOFT;
int nbSupportedModulation = 0; int nbSupportedModulation = 0;
if ((pnd->btSupportByte & SUPPORT_ISO14443A)) { if ((pnd->btSupportByte & SUPPORT_ISO14443A)) {
CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443A; CHIP_DATA(pnd)->supported_modulation_as_initiator[nbSupportedModulation] = NMT_ISO14443A;
@ -518,7 +520,6 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type
pnti->nii.btConfig = *(pbtRawData++); pnti->nii.btConfig = *(pbtRawData++);
if (pnti->nii.btConfig & 0x40) { if (pnti->nii.btConfig & 0x40) {
memcpy(pnti->nii.abtAtr, pbtRawData, szRawData - 8); memcpy(pnti->nii.abtAtr, pbtRawData, szRawData - 8);
pbtRawData += szRawData - 8;
pnti->nii.szAtrLen = szRawData - 8; pnti->nii.szAtrLen = szRawData - 8;
} }
} }
@ -527,7 +528,6 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type
case NMT_ISO14443B2SR: case NMT_ISO14443B2SR:
// Store the UID // Store the UID
memcpy(pnti->nsi.abtUID, pbtRawData, 8); memcpy(pnti->nsi.abtUID, pbtRawData, 8);
pbtRawData += 8;
break; break;
case NMT_ISO14443B2CT: case NMT_ISO14443B2CT:
@ -539,7 +539,6 @@ pn53x_decode_target_data(const uint8_t *pbtRawData, size_t szRawData, pn53x_type
pnti->nci.btFabCode = *(pbtRawData++); pnti->nci.btFabCode = *(pbtRawData++);
// Store UID MSB // Store UID MSB
memcpy(pnti->nci.abtUID + 2, pbtRawData, 2); memcpy(pnti->nci.abtUID + 2, pbtRawData, 2);
pbtRawData += 2;
break; break;
case NMT_FELICA: case NMT_FELICA:
@ -1454,7 +1453,7 @@ pn53x_initiator_transceive_bits_timed(struct nfc_device *pnd, const uint8_t *pbt
(void) pbtTxPar; (void) pbtTxPar;
(void) pbtRxPar; (void) pbtRxPar;
uint16_t i; uint16_t i;
uint8_t sz; uint8_t sz = 0;
int res = 0; int res = 0;
size_t szRxBits = 0; size_t szRxBits = 0;
@ -1553,7 +1552,7 @@ int
pn53x_initiator_transceive_bytes_timed(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, uint32_t *cycles) pn53x_initiator_transceive_bytes_timed(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, uint32_t *cycles)
{ {
uint16_t i; uint16_t i;
uint8_t sz; uint8_t sz = 0;
int res = 0; int res = 0;
// We can not just send bytes without parity while the PN53X expects we handled them // We can not just send bytes without parity while the PN53X expects we handled them
@ -1649,6 +1648,8 @@ pn53x_initiator_transceive_bytes_timed(struct nfc_device *pnd, const uint8_t *pb
// We've to compute CRC ourselves to know last byte actually sent // We've to compute CRC ourselves to know last byte actually sent
uint8_t *pbtTxRaw; uint8_t *pbtTxRaw;
pbtTxRaw = (uint8_t *) malloc(szTx + 2); pbtTxRaw = (uint8_t *) malloc(szTx + 2);
if (!pbtTxRaw)
return NFC_ESOFT;
memcpy(pbtTxRaw, pbtTx, szTx); memcpy(pbtTxRaw, pbtTx, szTx);
iso14443a_crc_append(pbtTxRaw, szTx); iso14443a_crc_append(pbtTxRaw, szTx);
*cycles = __pn53x_get_timer(pnd, pbtTxRaw[szTx + 1]); *cycles = __pn53x_get_timer(pnd, pbtTxRaw[szTx + 1]);
@ -2929,127 +2930,156 @@ pn53x_get_information_about(nfc_device *pnd, char **pbuf)
{ {
size_t buflen = 2048; size_t buflen = 2048;
*pbuf = malloc(buflen); *pbuf = malloc(buflen);
if (! *pbuf) {
return NFC_ESOFT;
}
char *buf = *pbuf; char *buf = *pbuf;
int res; int res;
if ((res = snprintf(buf, buflen, "chip: %s\n", CHIP_DATA(pnd)->firmware_text)) < 0) { if ((res = snprintf(buf, buflen, "chip: %s\n", CHIP_DATA(pnd)->firmware_text)) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
if ((res = snprintf(buf, buflen, "initator mode modulations: ")) < 0) { if ((res = snprintf(buf, buflen, "initator mode modulations: ")) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
const nfc_modulation_type *nmt; const nfc_modulation_type *nmt;
if ((res = nfc_device_get_supported_modulation(pnd, N_INITIATOR, &nmt)) < 0) { if ((res = nfc_device_get_supported_modulation(pnd, N_INITIATOR, &nmt)) < 0) {
free(*pbuf);
return res; return res;
} }
for (int i = 0; nmt[i]; i++) { for (int i = 0; nmt[i]; i++) {
if ((res = snprintf(buf, buflen, "%s%s (", (i == 0) ? "" : ", ", str_nfc_modulation_type(nmt[i]))) < 0) { if ((res = snprintf(buf, buflen, "%s%s (", (i == 0) ? "" : ", ", str_nfc_modulation_type(nmt[i]))) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
const nfc_baud_rate *nbr; const nfc_baud_rate *nbr;
if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) { if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) {
free(*pbuf);
return res; return res;
} }
for (int j = 0; nbr[j]; j++) { for (int j = 0; nbr[j]; j++) {
if ((res = snprintf(buf, buflen, "%s%s", (j == 0) ? "" : ", ", str_nfc_baud_rate(nbr[j]))) < 0) { if ((res = snprintf(buf, buflen, "%s%s", (j == 0) ? "" : ", ", str_nfc_baud_rate(nbr[j]))) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
} }
if ((res = snprintf(buf, buflen, ")")) < 0) { if ((res = snprintf(buf, buflen, ")")) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
} }
if ((res = snprintf(buf, buflen, "\n")) < 0) { if ((res = snprintf(buf, buflen, "\n")) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
if ((res = snprintf(buf, buflen, "target mode modulations: ")) < 0) { if ((res = snprintf(buf, buflen, "target mode modulations: ")) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
if ((res = nfc_device_get_supported_modulation(pnd, N_TARGET, &nmt)) < 0) { if ((res = nfc_device_get_supported_modulation(pnd, N_TARGET, &nmt)) < 0) {
free(*pbuf);
return res; return res;
} }
for (int i = 0; nmt[i]; i++) { for (int i = 0; nmt[i]; i++) {
if ((res = snprintf(buf, buflen, "%s%s (", (i == 0) ? "" : ", ", str_nfc_modulation_type(nmt[i]))) < 0) { if ((res = snprintf(buf, buflen, "%s%s (", (i == 0) ? "" : ", ", str_nfc_modulation_type(nmt[i]))) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
const nfc_baud_rate *nbr; const nfc_baud_rate *nbr;
if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) { if ((res = nfc_device_get_supported_baud_rate(pnd, nmt[i], &nbr)) < 0) {
free(*pbuf);
return res; return res;
} }
for (int j = 0; nbr[j]; j++) { for (int j = 0; nbr[j]; j++) {
if ((res = snprintf(buf, buflen, "%s%s", (j == 0) ? "" : ", ", str_nfc_baud_rate(nbr[j]))) < 0) { if ((res = snprintf(buf, buflen, "%s%s", (j == 0) ? "" : ", ", str_nfc_baud_rate(nbr[j]))) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
} }
if ((res = snprintf(buf, buflen, ")")) < 0) { if ((res = snprintf(buf, buflen, ")")) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; buflen -= res;
} }
if ((res = snprintf(buf, buflen, "\n")) < 0) { if ((res = snprintf(buf, buflen, "\n")) < 0) {
free(*pbuf);
return NFC_ESOFT; return NFC_ESOFT;
} }
buf += res; //buf += res;
if (buflen <= (size_t)res) { if (buflen <= (size_t)res) {
free(*pbuf);
return NFC_EOVFLOW; return NFC_EOVFLOW;
} }
buflen -= res; //buflen -= res;
return NFC_SUCCESS; return NFC_SUCCESS;
} }

View file

@ -66,6 +66,7 @@ conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const ch
regmatch_t *pmatch = malloc(sizeof(*pmatch) * nmatch); regmatch_t *pmatch = malloc(sizeof(*pmatch) * nmatch);
if (!pmatch) { if (!pmatch) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Not enough memory: malloc failed."); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Not enough memory: malloc failed.");
regfree(&preg);
return false; return false;
} }
@ -98,6 +99,7 @@ conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const ch
} }
free(pmatch); free(pmatch);
regfree(&preg);
return false; return false;
} }
@ -180,6 +182,7 @@ conf_devices_load(const char *dirname, nfc_context *context)
} }
} }
} }
closedir(d);
} }
} }

View file

@ -261,9 +261,15 @@ acr122_pcsc_open(const nfc_context *context, const nfc_connstring connstring)
if (sscanf(ndd.pcsc_device_name, "%lu", &index) != 1) if (sscanf(ndd.pcsc_device_name, "%lu", &index) != 1)
return NULL; return NULL;
nfc_connstring *ncs = malloc(sizeof(nfc_connstring) * (index + 1)); nfc_connstring *ncs = malloc(sizeof(nfc_connstring) * (index + 1));
size_t szDeviceFound = acr122_pcsc_scan(context, ncs, index + 1); if (!ncs) {
if (szDeviceFound < index + 1) perror("malloc");
return NULL; return NULL;
}
size_t szDeviceFound = acr122_pcsc_scan(context, ncs, index + 1);
if (szDeviceFound < index + 1) {
free(ncs);
return NULL;
}
strncpy(fullconnstring, ncs[index], sizeof(nfc_connstring)); strncpy(fullconnstring, ncs[index], sizeof(nfc_connstring));
free(ncs); free(ncs);
connstring_decode_level = acr122_pcsc_connstring_decode(fullconnstring, &ndd); connstring_decode_level = acr122_pcsc_connstring_decode(fullconnstring, &ndd);
@ -275,6 +281,10 @@ acr122_pcsc_open(const nfc_context *context, const nfc_connstring connstring)
char *pcFirmware; char *pcFirmware;
nfc_device *pnd = nfc_device_new(context, fullconnstring); nfc_device *pnd = nfc_device_new(context, fullconnstring);
pnd->driver_data = malloc(sizeof(struct acr122_pcsc_data)); pnd->driver_data = malloc(sizeof(struct acr122_pcsc_data));
if (!pnd->driver_data) {
perror("malloc");
goto error;
}
// Alloc and init chip's data // Alloc and init chip's data
pn53x_data_new(pnd, &acr122_pcsc_io); pn53x_data_new(pnd, &acr122_pcsc_io);

View file

@ -54,24 +54,12 @@ Thanks to d18c7db and Okko for example code
#include <inttypes.h> #include <inttypes.h>
#include <sys/select.h> #include <sys/select.h>
#include <errno.h> #include <errno.h>
#ifndef _WIN32
// Under POSIX system, we use libusb (>= 0.1.12)
#include <usb.h>
#define USB_TIMEDOUT ETIMEDOUT
#define _usb_strerror( X ) strerror(-X)
#else
// Under Windows we use libusb-win32 (>= 1.2.5)
#include <lusb0_usb.h>
#define USB_TIMEDOUT 116
#define _usb_strerror( X ) usb_strerror()
#endif
#include <string.h> #include <string.h>
#include <nfc/nfc.h> #include <nfc/nfc.h>
#include "nfc-internal.h" #include "nfc-internal.h"
#include "buses/usbbus.h"
#include "chips/pn53x.h" #include "chips/pn53x.h"
#include "chips/pn53x-internal.h" #include "chips/pn53x-internal.h"
#include "drivers/acr122_usb.h" #include "drivers/acr122_usb.h"
@ -172,6 +160,7 @@ struct acr122_usb_apdu_frame {
}; };
#pragma pack() #pragma pack()
// Internal data struct
struct acr122_usb_data { struct acr122_usb_data {
usb_dev_handle *pudh; usb_dev_handle *pudh;
acr122_usb_model model; acr122_usb_model model;
@ -203,7 +192,7 @@ const uint8_t acr122_usb_frame_template[] = {
// APDUs instructions // APDUs instructions
#define APDU_GetAdditionnalData 0xc0 #define APDU_GetAdditionnalData 0xc0
// Internal data struct // Internal io struct
const struct pn53x_io acr122_usb_io; const struct pn53x_io acr122_usb_io;
// Prototypes // Prototypes
@ -309,23 +298,8 @@ static size_t
acr122_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) acr122_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
{ {
(void)context; (void)context;
usb_init();
int res; usb_prepare();
// usb_find_busses will find all of the busses on the system. Returns the
// number of changes since previous call to this function (total of new
// busses and busses removed).
if ((res = usb_find_busses()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB busses (%s)", _usb_strerror(res));
return 0;
}
// usb_find_devices will find all of the devices on each bus. This should be
// called after usb_find_busses. Returns the number of changes since the
// previous call to this function (total of new device and devices removed).
if ((res = usb_find_devices()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB devices (%s)", _usb_strerror(res));
return 0;
}
size_t device_found = 0; size_t device_found = 0;
uint32_t uiBusIndex = 0; uint32_t uiBusIndex = 0;
@ -378,8 +352,23 @@ acr122_usb_connstring_decode(const nfc_connstring connstring, struct acr122_usb_
{ {
int n = strlen(connstring) + 1; int n = strlen(connstring) + 1;
char *driver_name = malloc(n); char *driver_name = malloc(n);
if (!driver_name) {
perror("malloc");
return 0;
}
char *dirname = malloc(n); char *dirname = malloc(n);
if (!dirname) {
perror("malloc");
free(driver_name);
return 0;
}
char *filename = malloc(n); char *filename = malloc(n);
if (!filename) {
perror("malloc");
free(driver_name);
free(dirname);
return 0;
}
driver_name[0] = '\0'; driver_name[0] = '\0';
@ -446,23 +435,7 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring)
struct usb_bus *bus; struct usb_bus *bus;
struct usb_device *dev; struct usb_device *dev;
usb_init(); usb_prepare();
int res;
// usb_find_busses will find all of the busses on the system. Returns the
// number of changes since previous call to this function (total of new
// busses and busses removed).
if ((res = usb_find_busses()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB busses (%s)", _usb_strerror(res));
goto free_mem;
}
// usb_find_devices will find all of the devices on each bus. This should be
// called after usb_find_busses. Returns the number of changes since the
// previous call to this function (total of new device and devices removed).
if ((res = usb_find_devices()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB devices (%s)", _usb_strerror(res));
goto free_mem;
}
for (bus = usb_get_busses(); bus; bus = bus->next) { for (bus = usb_get_busses(); bus; bus = bus->next) {
if (connstring_decode_level > 1) { if (connstring_decode_level > 1) {
@ -483,7 +456,7 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring)
// Retrieve end points // Retrieve end points
acr122_usb_get_end_points(dev, &data); acr122_usb_get_end_points(dev, &data);
// Claim interface // Claim interface
res = usb_claim_interface(data.pudh, 0); int res = usb_claim_interface(data.pudh, 0);
if (res < 0) { if (res < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", _usb_strerror(res)); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", _usb_strerror(res));
usb_close(data.pudh); usb_close(data.pudh);
@ -505,6 +478,10 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring)
acr122_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name)); acr122_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name));
pnd->driver_data = malloc(sizeof(struct acr122_usb_data)); pnd->driver_data = malloc(sizeof(struct acr122_usb_data));
if (!pnd->driver_data) {
perror("malloc");
goto error;
}
*DRIVER_DATA(pnd) = data; *DRIVER_DATA(pnd) = data;
// Alloc and init chip's data // Alloc and init chip's data
@ -584,13 +561,21 @@ acr122_build_frame_from_apdu(nfc_device *pnd, const uint8_t ins, const uint8_t p
{ {
if (data_len > sizeof(DRIVER_DATA(pnd)->apdu_frame.apdu_payload)) if (data_len > sizeof(DRIVER_DATA(pnd)->apdu_frame.apdu_payload))
return NFC_EINVARG; return NFC_EINVARG;
if ((data == NULL) && (data_len != 0))
return NFC_EINVARG;
DRIVER_DATA(pnd)->apdu_frame.ccid_header.dwLength = htole32(data_len + sizeof(struct apdu_header)); DRIVER_DATA(pnd)->apdu_frame.ccid_header.dwLength = htole32(data_len + sizeof(struct apdu_header));
DRIVER_DATA(pnd)->apdu_frame.apdu_header.bIns = ins; DRIVER_DATA(pnd)->apdu_frame.apdu_header.bIns = ins;
DRIVER_DATA(pnd)->apdu_frame.apdu_header.bP1 = p1; DRIVER_DATA(pnd)->apdu_frame.apdu_header.bP1 = p1;
DRIVER_DATA(pnd)->apdu_frame.apdu_header.bP2 = p2; DRIVER_DATA(pnd)->apdu_frame.apdu_header.bP2 = p2;
DRIVER_DATA(pnd)->apdu_frame.apdu_header.bLen = (data ? data_len : le); // XXX This line is a bit tricky ^^: bLen is Lc when data != NULL... otherwise its Le. if (data) {
// bLen is Lc when data != NULL
DRIVER_DATA(pnd)->apdu_frame.apdu_header.bLen = data_len;
memcpy(DRIVER_DATA(pnd)->apdu_frame.apdu_payload, data, data_len); memcpy(DRIVER_DATA(pnd)->apdu_frame.apdu_payload, data, data_len);
} else {
// bLen is Le when no data.
DRIVER_DATA(pnd)->apdu_frame.apdu_header.bLen = le;
}
return (sizeof(struct ccid_header) + sizeof(struct apdu_header) + data_len); return (sizeof(struct ccid_header) + sizeof(struct apdu_header) + data_len);
} }
@ -758,7 +743,6 @@ read:
offset += 1; offset += 1;
memcpy(pbtData, abtRxBuf + offset, len); memcpy(pbtData, abtRxBuf + offset, len);
offset += len;
return len; return len;
} }
@ -772,8 +756,8 @@ acr122_usb_ack(nfc_device *pnd)
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ACR122 Abort"); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ACR122 Abort");
if ((res = acr122_build_frame_from_tama(pnd, acr122_ack_frame, sizeof(acr122_ack_frame))) < 0) if ((res = acr122_build_frame_from_tama(pnd, acr122_ack_frame, sizeof(acr122_ack_frame))) < 0)
return res; return res;
if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) & (DRIVER_DATA(pnd)->tama_frame), res, 1000)) < 0)
res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) & (DRIVER_DATA(pnd)->tama_frame), res, 1000); return res;
uint8_t abtRxBuf[255 + sizeof(struct ccid_header)]; uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), 1000); res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), 1000);
return res; return res;

View file

@ -473,6 +473,10 @@ acr122s_scan(const nfc_context *context, nfc_connstring connstrings[], const siz
pnd->driver = &acr122s_driver; pnd->driver = &acr122s_driver;
pnd->driver_data = malloc(sizeof(struct acr122s_data)); pnd->driver_data = malloc(sizeof(struct acr122s_data));
if (!pnd->driver_data) {
perror("malloc");
return -1;
}
DRIVER_DATA(pnd)->port = sp; DRIVER_DATA(pnd)->port = sp;
DRIVER_DATA(pnd)->seq = 0; DRIVER_DATA(pnd)->seq = 0;
@ -574,6 +578,12 @@ acr122s_open(const nfc_context *context, const nfc_connstring connstring)
strcpy(pnd->name, ACR122S_DRIVER_NAME); strcpy(pnd->name, ACR122S_DRIVER_NAME);
pnd->driver_data = malloc(sizeof(struct acr122s_data)); pnd->driver_data = malloc(sizeof(struct acr122s_data));
if (!pnd->driver_data) {
perror("malloc");
acr122s_close(pnd);
return NULL;
}
DRIVER_DATA(pnd)->port = sp; DRIVER_DATA(pnd)->port = sp;
DRIVER_DATA(pnd)->seq = 0; DRIVER_DATA(pnd)->seq = 0;

View file

@ -117,6 +117,10 @@ arygon_scan(const nfc_context *context, nfc_connstring connstrings[], const size
pnd->driver = &arygon_driver; pnd->driver = &arygon_driver;
pnd->driver_data = malloc(sizeof(struct arygon_data)); pnd->driver_data = malloc(sizeof(struct arygon_data));
if (!pnd->driver_data) {
perror("malloc");
return 0;
}
DRIVER_DATA(pnd)->port = sp; DRIVER_DATA(pnd)->port = sp;
// Alloc and init chip's data // Alloc and init chip's data
@ -262,6 +266,10 @@ arygon_open(const nfc_context *context, const nfc_connstring connstring)
snprintf(pnd->name, sizeof(pnd->name), "%s:%s", ARYGON_DRIVER_NAME, ndd.port); snprintf(pnd->name, sizeof(pnd->name), "%s:%s", ARYGON_DRIVER_NAME, ndd.port);
pnd->driver_data = malloc(sizeof(struct arygon_data)); pnd->driver_data = malloc(sizeof(struct arygon_data));
if (!pnd->driver_data) {
perror("malloc");
return NULL;
}
DRIVER_DATA(pnd)->port = sp; DRIVER_DATA(pnd)->port = sp;
// Alloc and init chip's data // Alloc and init chip's data

View file

@ -90,6 +90,10 @@ pn532_uart_scan(const nfc_context *context, nfc_connstring connstrings[], const
nfc_device *pnd = nfc_device_new(context, connstring); nfc_device *pnd = nfc_device_new(context, connstring);
pnd->driver = &pn532_uart_driver; pnd->driver = &pn532_uart_driver;
pnd->driver_data = malloc(sizeof(struct pn532_uart_data)); pnd->driver_data = malloc(sizeof(struct pn532_uart_data));
if (!pnd->driver_data) {
perror("malloc");
return 0;
}
DRIVER_DATA(pnd)->port = sp; DRIVER_DATA(pnd)->port = sp;
// Alloc and init chip's data // Alloc and init chip's data
@ -239,6 +243,10 @@ pn532_uart_open(const nfc_context *context, const nfc_connstring connstring)
snprintf(pnd->name, sizeof(pnd->name), "%s:%s", PN532_UART_DRIVER_NAME, ndd.port); snprintf(pnd->name, sizeof(pnd->name), "%s:%s", PN532_UART_DRIVER_NAME, ndd.port);
pnd->driver_data = malloc(sizeof(struct pn532_uart_data)); pnd->driver_data = malloc(sizeof(struct pn532_uart_data));
if (!pnd->driver_data) {
perror("malloc");
return NULL;
}
DRIVER_DATA(pnd)->port = sp; DRIVER_DATA(pnd)->port = sp;
// Alloc and init chip's data // Alloc and init chip's data

View file

@ -37,24 +37,12 @@ Thanks to d18c7db and Okko for example code
#include <inttypes.h> #include <inttypes.h>
#include <sys/select.h> #include <sys/select.h>
#include <errno.h> #include <errno.h>
#ifndef _WIN32
// Under POSIX system, we use libusb (>= 0.1.12)
#include <usb.h>
#define USB_TIMEDOUT ETIMEDOUT
#define _usb_strerror( X ) strerror(-X)
#else
// Under Windows we use libusb-win32 (>= 1.2.5)
#include <lusb0_usb.h>
#define USB_TIMEDOUT 116
#define _usb_strerror( X ) usb_strerror()
#endif
#include <string.h> #include <string.h>
#include <nfc/nfc.h> #include <nfc/nfc.h>
#include "nfc-internal.h" #include "nfc-internal.h"
#include "buses/usbbus.h"
#include "chips/pn53x.h" #include "chips/pn53x.h"
#include "chips/pn53x-internal.h" #include "chips/pn53x-internal.h"
#include "drivers/pn53x_usb.h" #include "drivers/pn53x_usb.h"
@ -77,7 +65,7 @@ typedef enum {
SONY_RCS360 SONY_RCS360
} pn53x_usb_model; } pn53x_usb_model;
// Internal data structs // Internal data struct
struct pn53x_usb_data { struct pn53x_usb_data {
usb_dev_handle *pudh; usb_dev_handle *pudh;
pn53x_usb_model model; pn53x_usb_model model;
@ -87,6 +75,7 @@ struct pn53x_usb_data {
volatile bool abort_flag; volatile bool abort_flag;
}; };
// Internal io struct
const struct pn53x_io pn53x_usb_io; const struct pn53x_io pn53x_usb_io;
// Prototypes // Prototypes
@ -186,22 +175,8 @@ static size_t
pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
{ {
(void)context; (void)context;
usb_init();
int res; usb_prepare();
// usb_find_busses will find all of the busses on the system. Returns the
// number of changes since previous call to this function (total of new
// busses and busses removed).
if ((res = usb_find_busses()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB busses (%s)", _usb_strerror(res));
return 0;
}
// usb_find_devices will find all of the devices on each bus. This should be
// called after usb_find_busses. Returns the number of changes since the
// previous call to this function (total of new device and devices removed).
if ((res = usb_find_devices()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB devices (%s)", _usb_strerror(res));
return 0;
}
size_t device_found = 0; size_t device_found = 0;
uint32_t uiBusIndex = 0; uint32_t uiBusIndex = 0;
@ -227,7 +202,7 @@ pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const s
usb_dev_handle *udev = usb_open(dev); usb_dev_handle *udev = usb_open(dev);
// Set configuration // Set configuration
res = usb_set_configuration(udev, 1); int res = usb_set_configuration(udev, 1);
if (res < 0) { if (res < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror(res)); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror(res));
usb_close(udev); usb_close(udev);
@ -262,8 +237,23 @@ pn53x_usb_connstring_decode(const nfc_connstring connstring, struct pn53x_usb_de
{ {
int n = strlen(connstring) + 1; int n = strlen(connstring) + 1;
char *driver_name = malloc(n); char *driver_name = malloc(n);
if (!driver_name) {
perror("malloc");
return 0;
}
char *dirname = malloc(n); char *dirname = malloc(n);
if (!dirname) {
perror("malloc");
free(driver_name);
return 0;
}
char *filename = malloc(n); char *filename = malloc(n);
if (!filename) {
perror("malloc");
free(driver_name);
free(dirname);
return 0;
}
driver_name[0] = '\0'; driver_name[0] = '\0';
@ -330,23 +320,7 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring)
struct usb_bus *bus; struct usb_bus *bus;
struct usb_device *dev; struct usb_device *dev;
usb_init(); usb_prepare();
int res;
// usb_find_busses will find all of the busses on the system. Returns the
// number of changes since previous call to this function (total of new
// busses and busses removed).
if ((res = usb_find_busses()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB busses (%s)", _usb_strerror(res));
goto free_mem;
}
// usb_find_devices will find all of the devices on each bus. This should be
// called after usb_find_busses. Returns the number of changes since the
// previous call to this function (total of new device and devices removed).
if ((res = usb_find_devices()) < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB devices (%s)", _usb_strerror(res));
goto free_mem;
}
for (bus = usb_get_busses(); bus; bus = bus->next) { for (bus = usb_get_busses(); bus; bus = bus->next) {
if (connstring_decode_level > 1) { if (connstring_decode_level > 1) {
@ -365,7 +339,7 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring)
// Retrieve end points // Retrieve end points
pn53x_usb_get_end_points(dev, &data); pn53x_usb_get_end_points(dev, &data);
// Set configuration // Set configuration
res = usb_set_configuration(data.pudh, 1); int res = usb_set_configuration(data.pudh, 1);
if (res < 0) { if (res < 0) {
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror(res)); log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror(res));
if (EPERM == -res) { if (EPERM == -res) {
@ -389,6 +363,10 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring)
pn53x_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name)); pn53x_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name));
pnd->driver_data = malloc(sizeof(struct pn53x_usb_data)); pnd->driver_data = malloc(sizeof(struct pn53x_usb_data));
if (!pnd->driver_data) {
perror("malloc");
goto error;
}
*DRIVER_DATA(pnd) = data; *DRIVER_DATA(pnd) = data;
// Alloc and init chip's data // Alloc and init chip's data
@ -761,6 +739,7 @@ const struct pn53x_io pn53x_usb_io = {
const struct nfc_driver pn53x_usb_driver = { const struct nfc_driver pn53x_usb_driver = {
.name = PN53X_USB_DRIVER_NAME, .name = PN53X_USB_DRIVER_NAME,
.scan_type = NOT_INTRUSIVE,
.scan = pn53x_usb_scan, .scan = pn53x_usb_scan,
.open = pn53x_usb_open, .open = pn53x_usb_open,
.close = pn53x_usb_close, .close = pn53x_usb_close,

View file

@ -35,6 +35,7 @@
#define NFC_LOG_GROUP_CHIP 3 #define NFC_LOG_GROUP_CHIP 3
#define NFC_LOG_GROUP_DRIVER 4 #define NFC_LOG_GROUP_DRIVER 4
#define NFC_LOG_GROUP_COM 5 #define NFC_LOG_GROUP_COM 5
#define NFC_LOG_GROUP_LIBUSB 6
/* /*
To enable log only for one (or more) group, you can use this formula: To enable log only for one (or more) group, you can use this formula:

View file

@ -121,7 +121,7 @@ struct nfc_driver_list {
const struct nfc_driver_list *nfc_drivers = NULL; const struct nfc_driver_list *nfc_drivers = NULL;
static void static void
nfc_drivers_init() nfc_drivers_init(void)
{ {
#if defined (DRIVER_PN53X_USB_ENABLED) #if defined (DRIVER_PN53X_USB_ENABLED)
nfc_register_driver(&pn53x_usb_driver); nfc_register_driver(&pn53x_usb_driver);
@ -1294,6 +1294,8 @@ int
str_nfc_target(char **buf, const nfc_target nt, bool verbose) str_nfc_target(char **buf, const nfc_target nt, bool verbose)
{ {
*buf = malloc(4096); *buf = malloc(4096);
if (! *buf)
return NFC_ESOFT;
(*buf)[0] = '\0'; (*buf)[0] = '\0';
sprint_nfc_target(*buf, nt, verbose); sprint_nfc_target(*buf, nt, verbose);
return strlen(*buf); return strlen(*buf);

View file

@ -463,7 +463,7 @@ sprint_nfc_iso14443a_info(char *dst, const nfc_iso14443a_info nai, bool verbose)
break; break;
} }
if (! found_possible_match) { if (! found_possible_match) {
dst += sprintf(dst, "* Unknown card, sorry\n"); sprintf(dst, "* Unknown card, sorry\n");
} }
} }
} }
@ -477,7 +477,7 @@ sprint_nfc_felica_info(char *dst, const nfc_felica_info nfi, bool verbose)
dst += sprintf(dst, " Parameter (PAD): "); dst += sprintf(dst, " Parameter (PAD): ");
dst += sprint_hex(dst, nfi.abtPad, 8); dst += sprint_hex(dst, nfi.abtPad, 8);
dst += sprintf(dst, " System Code (SC): "); dst += sprintf(dst, " System Code (SC): ");
dst += sprint_hex(dst, nfi.abtSysCode, 2); sprint_hex(dst, nfi.abtSysCode, 2);
} }
void void
@ -487,7 +487,7 @@ sprint_nfc_jewel_info(char *dst, const nfc_jewel_info nji, bool verbose)
dst += sprintf(dst, " ATQA (SENS_RES): "); dst += sprintf(dst, " ATQA (SENS_RES): ");
dst += sprint_hex(dst, nji.btSensRes, 2); dst += sprint_hex(dst, nji.btSensRes, 2);
dst += sprintf(dst, " 4-LSB JEWELID: "); dst += sprintf(dst, " 4-LSB JEWELID: ");
dst += sprint_hex(dst, nji.btId, 4); sprint_hex(dst, nji.btId, 4);
} }
#define PI_ISO14443_4_SUPPORTED 0x01 #define PI_ISO14443_4_SUPPORTED 0x01
@ -543,7 +543,7 @@ sprint_nfc_iso14443b_info(char *dst, const nfc_iso14443b_info nbi, bool verbose)
dst += sprintf(dst, "* Frame options supported: "); dst += sprintf(dst, "* Frame options supported: ");
if ((nbi.abtProtocolInfo[2] & PI_NAD_SUPPORTED) != 0) dst += sprintf(dst, "NAD "); if ((nbi.abtProtocolInfo[2] & PI_NAD_SUPPORTED) != 0) dst += sprintf(dst, "NAD ");
if ((nbi.abtProtocolInfo[2] & PI_CID_SUPPORTED) != 0) dst += sprintf(dst, "CID "); if ((nbi.abtProtocolInfo[2] & PI_CID_SUPPORTED) != 0) dst += sprintf(dst, "CID ");
dst += sprintf(dst, "\n"); sprintf(dst, "\n");
} }
} }
} }
@ -568,7 +568,7 @@ sprint_nfc_iso14443bi_info(char *dst, const nfc_iso14443bi_info nii, bool verbos
} }
if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x40)) { if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x40)) {
dst += sprintf(dst, " ATS: "); dst += sprintf(dst, " ATS: ");
dst += sprint_hex(dst, nii.abtAtr, nii.szAtrLen); sprint_hex(dst, nii.abtAtr, nii.szAtrLen);
} }
} }
@ -577,7 +577,7 @@ sprint_nfc_iso14443b2sr_info(char *dst, const nfc_iso14443b2sr_info nsi, bool ve
{ {
(void) verbose; (void) verbose;
dst += sprintf(dst, " UID: "); dst += sprintf(dst, " UID: ");
dst += sprint_hex(dst, nsi.abtUID, 8); sprint_hex(dst, nsi.abtUID, 8);
} }
void void
@ -590,7 +590,7 @@ sprint_nfc_iso14443b2ct_info(char *dst, const nfc_iso14443b2ct_info nci, bool ve
dst += sprint_hex(dst, nci.abtUID, sizeof(nci.abtUID)); dst += sprint_hex(dst, nci.abtUID, sizeof(nci.abtUID));
dst += sprintf(dst, " UID (decimal): %010u\n", uid); dst += sprintf(dst, " UID (decimal): %010u\n", uid);
dst += sprintf(dst, " Product Code: %02X\n", nci.btProdCode); dst += sprintf(dst, " Product Code: %02X\n", nci.btProdCode);
dst += sprintf(dst, " Fab Code: %02X\n", nci.btFabCode); sprintf(dst, " Fab Code: %02X\n", nci.btFabCode);
} }
void void
@ -605,7 +605,7 @@ sprint_nfc_dep_info(char *dst, const nfc_dep_info ndi, bool verbose)
dst += sprintf(dst, " PP: %02x\n", ndi.btPP); dst += sprintf(dst, " PP: %02x\n", ndi.btPP);
if (ndi.szGB) { if (ndi.szGB) {
dst += sprintf(dst, "General Bytes: "); dst += sprintf(dst, "General Bytes: ");
dst += sprint_hex(dst, ndi.abtGB, ndi.szGB); sprint_hex(dst, ndi.abtGB, ndi.szGB);
} }
} }

View file

@ -38,12 +38,6 @@
# include "config.h" # include "config.h"
#endif // HAVE_CONFIG_H #endif // HAVE_CONFIG_H
#ifdef HAVE_LIBUSB
# ifdef DEBUG
# include <usb.h>
# endif
#endif
#include <err.h> #include <err.h>
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
@ -90,12 +84,6 @@ main(int argc, const char *argv[])
} }
} }
#ifdef HAVE_LIBUSB
# ifdef DEBUG
usb_set_debug(4);
# endif
#endif
/* Lazy way to open an NFC device */ /* Lazy way to open an NFC device */
#if 0 #if 0
pnd = nfc_open(context, NULL); pnd = nfc_open(context, NULL);

View file

@ -4,7 +4,7 @@ nfc-mfclassic \- MIFARE Classic command line tool
.SH SYNOPSIS .SH SYNOPSIS
.B nfc-mfclassic .B nfc-mfclassic
.RI \fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR .RI \fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR
.RI \fR\fBa\fR|\fBb\fR .RI \fR\fBa\fR|\fR\fBA\fR|\fBb\fR\fR|\fBB\fR
.IR DUMP .IR DUMP
.IR [KEYS] .IR [KEYS]
@ -27,16 +27,36 @@ to store the keys and data for all sectors.
Be cautious that some parts of a MIFARE Classic memory are used for r/w access Be cautious that some parts of a MIFARE Classic memory are used for r/w access
of the rest of the memory, so please read the tag documentation before experimenting too much! of the rest of the memory, so please read the tag documentation before experimenting too much!
The 'W' option allows writing of special MIFARE cards that can be 'unlocked' to allow block 0 The
.B W
option allows writing of special MIFARE cards that can be 'unlocked' to allow block 0
to be overwritten. This includes UID and manufacturer data. Take care when amending UIDs to set to be overwritten. This includes UID and manufacturer data. Take care when amending UIDs to set
the correct BCC (UID checksum). Currently only 4 byte UIDs are supported. the correct BCC (UID checksum). Currently only 4 byte UIDs are supported.
Similarly, the 'R' option allows an 'unlocked' read. This bypasses authentication and allows Similarly, the
.B R
option allows an 'unlocked' read. This bypasses authentication and allows
reading of the Key A and Key B data regardless of ACLs. reading of the Key A and Key B data regardless of ACLs.
*** Note that 'W' and 'R' options only work on special versions of MIFARE 1K cards (Chinese clones). R/W errors on some blocks can be either considered as critical or ignored.
To halt on first error, specify keys with lowercase (
.B a
or
.B b
). To ignore such errors, use uppercase (
.B A
or
.B B
).
*** Note that
.B W
and
.B R
options only work on special versions of MIFARE 1K cards (Chinese clones).
.SH OPTIONS .SH OPTIONS
.TP
.BR r " | " R " | " w " | " W .BR r " | " R " | " w " | " W
Perform read from ( Perform read from (
.B r .B r
@ -48,8 +68,18 @@ Perform read from (
.B W .B W
) card. ) card.
.TP .TP
.BR a " | " b .BR a " | " A " | " b " | " B
Use A or B MIFARE keys. Use A or B MIFARE keys.
Halt on errors (
.B a
|
.B b
) or tolerate errors (
.B A
|
.B
B
).
.TP .TP
.IR DUMP .IR DUMP
MiFare Dump (MFD) used to write (card to MFD) or (MFD to card) MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)

View file

@ -61,6 +61,7 @@ static mifare_classic_tag mtKeys;
static mifare_classic_tag mtDump; static mifare_classic_tag mtDump;
static bool bUseKeyA; static bool bUseKeyA;
static bool bUseKeyFile; static bool bUseKeyFile;
static bool bTolerateFailures;
static uint8_t uiBlocks; static uint8_t uiBlocks;
static uint8_t keys[] = { static uint8_t keys[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@ -268,18 +269,11 @@ read_card(int read_unlocked)
if (!unlock_card()) if (!unlock_card())
return false; return false;
printf("Reading out %d blocks |", uiBlocks + 1); printf("Reading out %d blocks |", uiBlocks + 1);
// Read the card from end to begin // Read the card from end to begin
for (iBlock = uiBlocks; iBlock >= 0; iBlock--) { for (iBlock = uiBlocks; iBlock >= 0; iBlock--) {
// Authenticate everytime we reach a trailer block // Authenticate everytime we reach a trailer block
if (is_trailer_block(iBlock)) { if (is_trailer_block(iBlock)) {
// Skip this the first time, bFailure it means nothing (yet)
if (iBlock != uiBlocks)
print_success_or_failure(bFailure, &uiReadBlocks);
// Show if the readout went well
if (bFailure) { if (bFailure) {
// When a failure occured we need to redo the anti-collision // When a failure occured we need to redo the anti-collision
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
@ -307,7 +301,8 @@ read_card(int read_unlocked)
memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6); memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6);
} }
} else { } else {
printf("!\nError: unable to read trailer block 0x%02x\n", iBlock); printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
bFailure = true;
} }
} else { } else {
// Make sure a earlier readout did not fail // Make sure a earlier readout did not fail
@ -316,14 +311,16 @@ read_card(int read_unlocked)
if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) { if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) {
memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16); memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
} else { } else {
bFailure = true;
printf("!\nError: unable to read block 0x%02x\n", iBlock); printf("!\nError: unable to read block 0x%02x\n", iBlock);
bFailure = true;
}
}
}
// Show if the readout went well for each block
print_success_or_failure(bFailure, &uiReadBlocks);
if ((! bTolerateFailures) && bFailure)
return false; return false;
} }
}
}
}
print_success_or_failure(bFailure, &uiReadBlocks);
printf("|\n"); printf("|\n");
printf("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1); printf("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1);
fflush(stdout); fflush(stdout);
@ -338,7 +335,6 @@ write_card(int write_block_zero)
bool bFailure = false; bool bFailure = false;
uint32_t uiWriteBlocks = 0; uint32_t uiWriteBlocks = 0;
if (write_block_zero) if (write_block_zero)
if (!unlock_card()) if (!unlock_card())
return false; return false;
@ -348,11 +344,6 @@ write_card(int write_block_zero)
for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
// Authenticate everytime we reach the first sector of a new block // Authenticate everytime we reach the first sector of a new block
if (is_first_block(uiBlock)) { if (is_first_block(uiBlock)) {
// Skip this the first time, bFailure it means nothing (yet)
if (uiBlock != 0)
print_success_or_failure(bFailure, &uiWriteBlocks);
// Show if the readout went well
if (bFailure) { if (bFailure) {
// When a failure occured we need to redo the anti-collision // When a failure occured we need to redo the anti-collision
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
@ -403,8 +394,11 @@ write_card(int write_block_zero)
bFailure = true; bFailure = true;
} }
} }
} // Show if the write went well for each block
print_success_or_failure(bFailure, &uiWriteBlocks); print_success_or_failure(bFailure, &uiWriteBlocks);
if ((! bTolerateFailures) && bFailure)
return false;
}
printf("|\n"); printf("|\n");
printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
fflush(stdout); fflush(stdout);
@ -427,7 +421,7 @@ print_usage(const char *pcProgramName)
printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n"); printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n");
printf(" *** unlocked read does not require authentication and will reveal A and B keys\n"); printf(" *** unlocked read does not require authentication and will reveal A and B keys\n");
printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n"); printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n");
printf(" a|b - Use A or B keys for action\n"); printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n"); printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
} }
@ -456,6 +450,7 @@ main(int argc, const char *argv[])
if (strcmp(command, "R") == 0) if (strcmp(command, "R") == 0)
unlock = 1; unlock = 1;
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
bUseKeyFile = (argc > 4); bUseKeyFile = (argc > 4);
} else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0) { } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0) {
if (argc < 4) { if (argc < 4) {
@ -466,6 +461,7 @@ main(int argc, const char *argv[])
if (strcmp(command, "W") == 0) if (strcmp(command, "W") == 0)
unlock = 1; unlock = 1;
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
bUseKeyFile = (argc > 4); bUseKeyFile = (argc > 4);
} }

View file

@ -28,10 +28,10 @@ to allow intrusive scan (eg. serial ports scan). This is equivalent to set envir
.SH EXAMPLE .SH EXAMPLE
For a SCL3711 device (in verbose mode): For a SCL3711 device (in verbose mode):
- ACS / ACR122U PICC Interface: - SCM Micro / SCL3711-NFC&RW:
acr122_usb:002:005 pn53x_usb:002:017
chip: PN532 v1.4 chip: PN533 v2.7
initator mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), ISO/IEC 14443-4B (106 kbps), Innovision Jewel (106 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) initator mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), ISO/IEC 14443-4B (847 kbps, 424 kbps, 212 kbps, 106 kbps), Innovision Jewel (106 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps)
target mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps) target mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps)
.SH BUGS .SH BUGS

View file

@ -38,12 +38,6 @@
# include "config.h" # include "config.h"
#endif // HAVE_CONFIG_H #endif // HAVE_CONFIG_H
#ifdef HAVE_LIBUSB
# ifdef DEBUG
# include <usb.h>
# endif
#endif
#include <err.h> #include <err.h>
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
@ -101,12 +95,6 @@ main(int argc, const char *argv[])
acLibnfcVersion = nfc_version(); acLibnfcVersion = nfc_version();
printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion); printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
#ifdef HAVE_LIBUSB
# ifdef DEBUG
usb_set_debug(4);
# endif
#endif
nfc_connstring connstrings[MAX_DEVICE_COUNT]; nfc_connstring connstrings[MAX_DEVICE_COUNT];
size_t szDeviceFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT); size_t szDeviceFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT);