mirror of
https://github.com/Sucareto/ESP32-CardReader.git
synced 2024-11-27 17:00:57 +01:00
同步更新,移除不再使用的库文件。
This commit is contained in:
parent
47515a42d6
commit
0c3fbcc07b
390
ReaderCmd.h
390
ReaderCmd.h
@ -1,12 +1,55 @@
|
|||||||
#include "src/PN532_SPI.h"
|
#ifdef ESP32
|
||||||
PN532_SPI pn532(SPI, PN532_SPI_SS);
|
#pragma message "当前的开发板是 ESP32"
|
||||||
|
#define SerialDevice Serial
|
||||||
|
#define LED_PIN 13
|
||||||
|
#define PN532_SPI_SS 5
|
||||||
|
|
||||||
#include "src/PN532.h"
|
#define SW1_MODE 33
|
||||||
PN532 nfc(pn532);
|
#define SW2_OTA 25
|
||||||
|
#define SW3_CARD 26
|
||||||
|
#define SW4_FW 27
|
||||||
|
|
||||||
|
// #define OTA_Enable
|
||||||
|
#ifdef OTA_Enable
|
||||||
|
#pragma message "已开启 OTA 更新功能"
|
||||||
|
#define STASSID "SSIDNAME"
|
||||||
|
#define STAPASS "PASSWORD"
|
||||||
|
#define OTA_URL "http://esp-update.local/Sucareto/ESP32-Reader:2333/"
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <HTTPUpdate.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "未适配的开发板!!!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define old_fw_version "TN32MSEC003S F/W Ver1.2"
|
||||||
|
#define old_hw_version "TN32MSEC003S H/W Ver3.0"
|
||||||
|
#define old_led_info "15084\xFF\x10\x00\x12"
|
||||||
|
|
||||||
|
#define new_fw_version "\x94"
|
||||||
|
#define new_hw_version "837-15396"
|
||||||
|
#define new_led_info "000-00000\xFF\x11\x40"
|
||||||
|
|
||||||
|
bool ReaderMode, FWSW;
|
||||||
|
uint8_t len, r, checksum;
|
||||||
|
bool escape = false;
|
||||||
|
unsigned long ConnectTime = 0;
|
||||||
|
bool ConnectStatus = false;
|
||||||
|
uint16_t SleepDelay = 10000; // ms
|
||||||
|
|
||||||
#include "FastLED.h"
|
#include "FastLED.h"
|
||||||
CRGB leds[8];
|
CRGB leds[8];
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <PN532_SPI.h>
|
||||||
|
PN532_SPI pn532(SPI, PN532_SPI_SS);
|
||||||
|
|
||||||
|
#include "PN532.h"
|
||||||
|
PN532 nfc(pn532);
|
||||||
|
uint8_t KeyA[6], KeyB[6];
|
||||||
|
uint8_t DefaultKey[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||||
|
|
||||||
#include <U8g2lib.h>
|
#include <U8g2lib.h>
|
||||||
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);
|
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);
|
||||||
|
|
||||||
@ -22,14 +65,6 @@ static uint8_t mifare_data[][16] = {
|
|||||||
{ 0x57, 0x43, 0x43, 0x46, 0x76, 0x32, 0x08, 0x77, 0x8F, 0x11, 0x57, 0x43, 0x43, 0x46, 0x76, 0x32 },
|
{ 0x57, 0x43, 0x43, 0x46, 0x76, 0x32, 0x08, 0x77, 0x8F, 0x11, 0x57, 0x43, 0x43, 0x46, 0x76, 0x32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
// static unsigned char usb_disconnect[] = {
|
|
||||||
// 0x00, 0x40, 0x00, 0xAE, 0x00, 0x51, 0x80, 0x20, 0x00, 0x41, 0x80, 0x42, 0x40, 0x44, 0x08, 0x28,
|
|
||||||
// 0x14, 0x14, 0x22, 0x02, 0x42, 0x00, 0x82, 0x00, 0x04, 0x01, 0x8A, 0x00, 0x75, 0x00, 0x02, 0x00
|
|
||||||
// };
|
|
||||||
// static unsigned char usb_connect[] = {
|
|
||||||
// 0x00, 0x40, 0x00, 0xA0, 0x00, 0x51, 0x80, 0x2A, 0x60, 0x14, 0x50, 0x08, 0xB0, 0x10, 0x48, 0x21,
|
|
||||||
// 0x84, 0x12, 0x08, 0x0D, 0x10, 0x0A, 0x28, 0x06, 0x54, 0x01, 0x8A, 0x00, 0x05, 0x00, 0x02, 0x00
|
|
||||||
// };
|
|
||||||
static unsigned char rf_open[] = {
|
static unsigned char rf_open[] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x02, 0x40, 0x02, 0x40, 0x11, 0x88, 0x91, 0x89, 0x49, 0x92,
|
0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x02, 0x40, 0x02, 0x40, 0x11, 0x88, 0x91, 0x89, 0x49, 0x92,
|
||||||
0x49, 0x92, 0x91, 0x89, 0x11, 0x88, 0x02, 0x40, 0x02, 0x40, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00
|
0x49, 0x92, 0x91, 0x89, 0x11, 0x88, 0x02, 0x40, 0x02, 0x40, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00
|
||||||
@ -39,6 +74,7 @@ static unsigned char rf_off[] = {
|
|||||||
0x01, 0x00, 0x02, 0x00, 0x04, 0x20, 0x0A, 0x40, 0x12, 0x40, 0x21, 0x88, 0x51, 0x89, 0x89, 0x92,
|
0x01, 0x00, 0x02, 0x00, 0x04, 0x20, 0x0A, 0x40, 0x12, 0x40, 0x21, 0x88, 0x51, 0x89, 0x89, 0x92,
|
||||||
0x49, 0x93, 0x91, 0x8A, 0x11, 0x8C, 0x02, 0x48, 0x02, 0x50, 0x04, 0x20, 0x00, 0x40, 0x00, 0x80
|
0x49, 0x93, 0x91, 0x8A, 0x11, 0x8C, 0x02, 0x48, 0x02, 0x50, 0x04, 0x20, 0x00, 0x40, 0x00, 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned char card[] = {
|
static unsigned char card[] = {
|
||||||
0x00, 0x00, 0xFC, 0x3F, 0x02, 0x40, 0x32, 0x48, 0x52, 0x48, 0x92, 0x48, 0x12, 0x49, 0x12, 0x4A,
|
0x00, 0x00, 0xFC, 0x3F, 0x02, 0x40, 0x32, 0x48, 0x52, 0x48, 0x92, 0x48, 0x12, 0x49, 0x12, 0x4A,
|
||||||
0x52, 0x48, 0x92, 0x48, 0x12, 0x49, 0x12, 0x4A, 0x12, 0x4C, 0x02, 0x40, 0xFC, 0x3F, 0x00, 0x00
|
0x52, 0x48, 0x92, 0x48, 0x12, 0x49, 0x12, 0x4A, 0x12, 0x4C, 0x02, 0x40, 0xFC, 0x3F, 0x00, 0x00
|
||||||
@ -49,47 +85,58 @@ static unsigned char blank[] = {
|
|||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t AimeKey[6], BanaKey[6], MifareKey[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
|
||||||
|
|
||||||
//TN32MSEC003S
|
|
||||||
char FW_TN32[] = { 'T', 'N', '3', '2', 'M', 'S', 'E', 'C', '0', '0', '3', 'S', ' ', 'F', '/', 'W', ' ', 'V', 'e', 'r', '1', '.', '2' };
|
|
||||||
char HW_TN32[] = { 'T', 'N', '3', '2', 'M', 'S', 'E', 'C', '0', '0', '3', 'S', ' ', 'H', '/', 'W', ' ', 'V', 'e', 'r', '3', '.', '0' };
|
|
||||||
char BOARD_TN32[] = { '1', '5', '0', '8', '4', 0xFF, 0x10, 0x00, 0x12 };
|
|
||||||
|
|
||||||
//837-15396
|
|
||||||
char FW_837[] = { 0x94 };
|
|
||||||
char HW_837[] = { '8', '3', '7', '-', '1', '5', '3', '9', '6' };
|
|
||||||
char BOARD_837[] = { '0', '0', '0', '-', '0', '0', '0', '0', '0', 0xFF, 0x11, 0x40 };
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SG_NFC_CMD_GET_FW_VERSION = 0x30,
|
CMD_GET_FW_VERSION = 0x30,
|
||||||
SG_NFC_CMD_GET_HW_VERSION = 0x32,
|
CMD_GET_HW_VERSION = 0x32,
|
||||||
SG_NFC_CMD_RADIO_ON = 0x40,
|
// Card read
|
||||||
SG_NFC_CMD_RADIO_OFF = 0x41,
|
CMD_START_POLLING = 0x40,
|
||||||
SG_NFC_CMD_POLL = 0x42,
|
CMD_STOP_POLLING = 0x41,
|
||||||
SG_NFC_CMD_MIFARE_SELECT_TAG = 0x43,
|
CMD_CARD_DETECT = 0x42,
|
||||||
SG_NFC_CMD_MIFARE_SET_KEY_BANA = 0x50,
|
CMD_CARD_SELECT = 0x43,
|
||||||
SG_NFC_CMD_BANA_AUTHENTICATE = 0x51,
|
CMD_CARD_HALT = 0x44,
|
||||||
SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52,
|
// MIFARE
|
||||||
SG_NFC_CMD_MIFARE_SET_KEY_AIME = 0x54,
|
CMD_MIFARE_KEY_SET_A = 0x50,
|
||||||
SG_NFC_CMD_AIME_AUTHENTICATE = 0x55,
|
CMD_MIFARE_AUTHORIZE_A = 0x51,
|
||||||
SG_NFC_CMD_TO_UPDATER_MODE = 0x60,
|
CMD_MIFARE_READ = 0x52,
|
||||||
SG_NFC_CMD_SEND_HEX_DATA = 0x61,
|
CMD_MIFARE_WRITE = 0x53,
|
||||||
SG_NFC_CMD_RESET = 0x62,
|
CMD_MIFARE_KEY_SET_B = 0x54,
|
||||||
SG_NFC_CMD_FELICA_ENCAP = 0x71,
|
CMD_MIFARE_AUTHORIZE_B = 0x55,
|
||||||
SG_RGB_CMD_SET_COLOR = 0x81,
|
// Boot,update
|
||||||
SG_RGB_CMD_GET_INFO = 0xF0,
|
CMD_TO_UPDATER_MODE = 0x60,
|
||||||
SG_RGB_CMD_RESET = 0xF5,
|
CMD_SEND_HEX_DATA = 0x61,
|
||||||
|
CMD_TO_NORMAL_MODE = 0x62,
|
||||||
//FELICA_ENCAP
|
CMD_SEND_BINDATA_INIT = 0x63,
|
||||||
FELICA_CMD_POLL = 0x00,
|
CMD_SEND_BINDATA_EXEC = 0x64,
|
||||||
FELICA_CMD_NDA_06 = 0x06,
|
// FeliCa
|
||||||
FELICA_CMD_NDA_08 = 0x08,
|
CMD_FELICA_PUSH = 0x70,
|
||||||
FELICA_CMD_GET_SYSTEM_CODE = 0x0C,
|
CMD_FELICA_THROUGH = 0x71,
|
||||||
FELICA_CMD_NDA_A4 = 0xA4,
|
CMD_FELICA_THROUGH_POLL = 0x00,
|
||||||
|
CMD_FELICA_THROUGH_READ = 0x06,
|
||||||
|
CMD_FELICA_THROUGH_WRITE = 0x08,
|
||||||
|
CMD_FELICA_THROUGH_GET_SYSTEM_CODE = 0x0C,
|
||||||
|
CMD_FELICA_THROUGH_NDA_A4 = 0xA4,
|
||||||
|
// LED board
|
||||||
|
CMD_EXT_BOARD_LED = 0x80,
|
||||||
|
CMD_EXT_BOARD_LED_RGB = 0x81,
|
||||||
|
CMD_EXT_BOARD_LED_RGB_UNKNOWN = 0x82, // 未知
|
||||||
|
CMD_EXT_BOARD_INFO = 0xf0,
|
||||||
|
CMD_EXT_FIRM_SUM = 0xf2,
|
||||||
|
CMD_EXT_SEND_HEX_DATA = 0xf3,
|
||||||
|
CMD_EXT_TO_BOOT_MODE = 0xf4,
|
||||||
|
CMD_EXT_TO_NORMAL_MODE = 0xf5,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union packet_req {
|
enum { // 未确认效果
|
||||||
|
ERROR_NONE = 0,
|
||||||
|
ERROR_NFCRW_INIT_ERROR = 1,
|
||||||
|
ERROR_NFCRW_FIRMWARE_UP_TO_DATE = 3,
|
||||||
|
ERROR_NFCRW_ACCESS_ERROR = 4,
|
||||||
|
ERROR_CARD_DETECT_TIMEOUT = 5,
|
||||||
|
ERROR_CARD_DETECT_ERROR = 32,
|
||||||
|
ERROR_FELICA_ERROR = 33,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union {
|
||||||
uint8_t bytes[128];
|
uint8_t bytes[128];
|
||||||
struct {
|
struct {
|
||||||
uint8_t frame_len;
|
uint8_t frame_len;
|
||||||
@ -98,38 +145,38 @@ typedef union packet_req {
|
|||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
uint8_t payload_len;
|
uint8_t payload_len;
|
||||||
union {
|
union {
|
||||||
uint8_t key[6]; //sg_nfc_req_mifare_set_key(bana or aime)
|
uint8_t key[6]; // CMD_MIFARE_KEY_SET
|
||||||
uint8_t color_payload[3]; //sg_led_req_set_color
|
uint8_t color_payload[3]; // CMD_EXT_BOARD_LED_RGB
|
||||||
struct { //sg_nfc_cmd_mifare_select_tag,sg_nfc_cmd_mifare_authenticate,sg_nfc_cmd_mifare_read_block
|
struct { // CMD_CARD_SELECT,AUTHORIZE,READ
|
||||||
uint8_t uid[4];
|
uint8_t uid[4];
|
||||||
uint8_t block_no;
|
uint8_t block_no;
|
||||||
};
|
};
|
||||||
struct { //sg_nfc_req_felica_encap
|
struct { // CMD_FELICA_THROUGH
|
||||||
uint8_t encap_IDm[8];
|
uint8_t encap_IDm[8];
|
||||||
uint8_t encap_len;
|
uint8_t encap_len;
|
||||||
uint8_t encap_code;
|
uint8_t encap_code;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct { // CMD_FELICA_THROUGH_POLL
|
||||||
uint8_t poll_systemCode[2];
|
uint8_t poll_systemCode[2];
|
||||||
uint8_t poll_requestCode;
|
uint8_t poll_requestCode;
|
||||||
uint8_t poll_timeout;
|
uint8_t poll_timeout;
|
||||||
};
|
};
|
||||||
struct { //NDA_06,NDA_08,NDA_A4
|
struct { // CMD_FELICA_THROUGH_READ,WRITE,NDA_A4
|
||||||
uint8_t RW_IDm[8];
|
uint8_t RW_IDm[8];
|
||||||
uint8_t numService; //and NDA_A4 unknown byte
|
uint8_t numService;
|
||||||
uint8_t serviceCodeList[2];
|
uint8_t serviceCodeList[2];
|
||||||
uint8_t numBlock;
|
uint8_t numBlock;
|
||||||
uint8_t blockList[1][2];
|
uint8_t blockList[1][2]; // CMD_FELICA_THROUGH_READ
|
||||||
uint8_t blockData[16]; //WriteWithoutEncryption,ignore
|
uint8_t blockData[16]; // CMD_FELICA_THROUGH_WRITE
|
||||||
};
|
};
|
||||||
uint8_t felica_payload[1];
|
uint8_t felica_payload[1];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} packet_req_t;
|
} packet_request_t;
|
||||||
|
|
||||||
typedef union packet_res {
|
typedef union {
|
||||||
uint8_t bytes[128];
|
uint8_t bytes[128];
|
||||||
struct {
|
struct {
|
||||||
uint8_t frame_len;
|
uint8_t frame_len;
|
||||||
@ -139,9 +186,9 @@ typedef union packet_res {
|
|||||||
uint8_t status;
|
uint8_t status;
|
||||||
uint8_t payload_len;
|
uint8_t payload_len;
|
||||||
union {
|
union {
|
||||||
char version[1]; //sg_nfc_res_get_fw_version,sg_nfc_res_get_hw_version,sg_led_res_get_info
|
uint8_t version[1]; // CMD_GET_FW_VERSION,CMD_GET_HW_VERSION,CMD_EXT_BOARD_INFO
|
||||||
uint8_t block[16]; //sg_nfc_res_mifare_read_block
|
uint8_t block[16]; // CMD_MIFARE_READ
|
||||||
struct { //sg_nfc_res_poll
|
struct { // CMD_CARD_DETECT
|
||||||
uint8_t count;
|
uint8_t count;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t id_len;
|
uint8_t id_len;
|
||||||
@ -153,33 +200,31 @@ typedef union packet_res {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
struct { //sg_nfc_res_felica_encap
|
struct { // CMD_FELICA_THROUGH
|
||||||
uint8_t encap_len;
|
uint8_t encap_len;
|
||||||
uint8_t encap_code;
|
uint8_t encap_code;
|
||||||
uint8_t encap_IDm[8];
|
uint8_t encap_IDm[8];
|
||||||
union {
|
union {
|
||||||
struct { //FELICA_CMD_POLL
|
struct { // FELICA_CMD_POLL
|
||||||
uint8_t poll_PMm[8];
|
uint8_t poll_PMm[8];
|
||||||
uint8_t poll_systemCode[2];
|
uint8_t poll_systemCode[2];
|
||||||
};
|
};
|
||||||
struct {
|
struct {
|
||||||
uint8_t RW_status[2]; //猜测,NDA_06,NDA_08
|
uint8_t RW_status[2];
|
||||||
uint8_t numBlock; //NDA_06
|
uint8_t numBlock;
|
||||||
uint8_t blockData[1][1][16]; //NDA_06
|
uint8_t blockData[1][1][16];
|
||||||
};
|
};
|
||||||
uint8_t felica_payload[1];
|
uint8_t felica_payload[1];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} packet_res_t;
|
} packet_response_t;
|
||||||
|
|
||||||
static packet_req_t req;
|
packet_request_t req;
|
||||||
static packet_res_t res;
|
packet_response_t res;
|
||||||
static uint8_t len, r, checksum;
|
|
||||||
static bool escape = false;
|
|
||||||
|
|
||||||
static uint8_t packet_read() {
|
uint8_t packet_read() {
|
||||||
while (SerialDevice.available()) {
|
while (SerialDevice.available()) {
|
||||||
r = SerialDevice.read();
|
r = SerialDevice.read();
|
||||||
if (r == 0xE0) {
|
if (r == 0xE0) {
|
||||||
@ -209,7 +254,7 @@ static uint8_t packet_read() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void packet_write() {
|
void packet_write() {
|
||||||
uint8_t checksum = 0, len = 0;
|
uint8_t checksum = 0, len = 0;
|
||||||
if (res.cmd == 0) {
|
if (res.cmd == 0) {
|
||||||
return;
|
return;
|
||||||
@ -234,228 +279,183 @@ static void packet_write() {
|
|||||||
res.cmd = 0;
|
res.cmd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_res_init(uint8_t payload_len = 0) { //初始化模板
|
void res_init(uint8_t payload_len = 0) {
|
||||||
res.frame_len = 6 + payload_len;
|
res.frame_len = 6 + payload_len;
|
||||||
res.addr = req.addr;
|
res.addr = req.addr;
|
||||||
res.seq_no = req.seq_no;
|
res.seq_no = req.seq_no;
|
||||||
res.cmd = req.cmd;
|
res.cmd = req.cmd;
|
||||||
res.status = 0;
|
res.status = ERROR_NONE;
|
||||||
res.payload_len = payload_len;
|
res.payload_len = payload_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_reset() {
|
void sys_to_normal_mode() {
|
||||||
|
res_init();
|
||||||
if (nfc.getFirmwareVersion()) {
|
if (nfc.getFirmwareVersion()) {
|
||||||
sg_res_init();
|
res.status = ERROR_NFCRW_FIRMWARE_UP_TO_DATE;
|
||||||
res.status = 3;
|
|
||||||
u8g2.drawXBM(95, 0, 16, 16, blank);
|
u8g2.drawXBM(95, 0, 16, 16, blank);
|
||||||
u8g2.drawXBM(113, 0, 16, 16, blank);
|
u8g2.drawXBM(113, 0, 16, 16, blank);
|
||||||
u8g2.sendBuffer();
|
} else {
|
||||||
return;
|
res.status = ERROR_NFCRW_INIT_ERROR;
|
||||||
}
|
|
||||||
u8g2.drawXBM(95, 0, 16, 16, rf_off);
|
u8g2.drawXBM(95, 0, 16, 16, rf_off);
|
||||||
u8g2.sendBuffer();
|
FastLED.showColor(0xFF0000);
|
||||||
FastLED.showColor(CRGB::Red);
|
|
||||||
while (true) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sg_nfc_cmd_get_fw_version() {
|
|
||||||
if (FWSW) {
|
|
||||||
sg_res_init(sizeof(FW_TN32));
|
|
||||||
memcpy(res.version, FW_TN32, res.payload_len);
|
|
||||||
} else {
|
|
||||||
sg_res_init(sizeof(FW_837));
|
|
||||||
memcpy(res.version, FW_837, res.payload_len);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_get_hw_version() {
|
void sys_get_fw_version() {
|
||||||
if (FWSW) {
|
if (FWSW) {
|
||||||
sg_res_init(sizeof(HW_TN32));
|
res_init(sizeof(old_fw_version) - 1);
|
||||||
memcpy(res.version, HW_TN32, res.payload_len);
|
memcpy(res.version, old_fw_version, res.payload_len);
|
||||||
} else {
|
} else {
|
||||||
sg_res_init(sizeof(HW_837));
|
res_init(sizeof(new_fw_version) - 1);
|
||||||
memcpy(res.version, HW_837, res.payload_len);
|
memcpy(res.version, new_fw_version, res.payload_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_led_cmd_get_info() {
|
void sys_get_hw_version() {
|
||||||
if (FWSW) {
|
if (FWSW) {
|
||||||
sg_res_init(sizeof(BOARD_TN32));
|
res_init(sizeof(old_hw_version) - 1);
|
||||||
memcpy(res.version, BOARD_TN32, res.payload_len);
|
memcpy(res.version, old_hw_version, res.payload_len);
|
||||||
} else {
|
} else {
|
||||||
sg_res_init(sizeof(BOARD_837));
|
res_init(sizeof(new_hw_version));
|
||||||
memcpy(res.version, BOARD_837, res.payload_len);
|
memcpy(res.version, new_hw_version, res.payload_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_mifare_set_key_aime() {
|
void sys_get_led_info() {
|
||||||
sg_res_init();
|
if (FWSW) {
|
||||||
memcpy(AimeKey, req.key, 6);
|
res_init(sizeof(old_led_info) - 1);
|
||||||
|
memcpy(res.version, old_led_info, res.payload_len);
|
||||||
|
} else {
|
||||||
|
res_init(sizeof(new_led_info) - 1);
|
||||||
|
memcpy(res.version, new_led_info, res.payload_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_mifare_set_key_bana() {
|
|
||||||
sg_res_init();
|
|
||||||
memcpy(BanaKey, req.key, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sg_led_cmd_reset() {
|
void nfc_start_polling() {
|
||||||
sg_res_init();
|
res_init();
|
||||||
}
|
|
||||||
|
|
||||||
static void sg_led_cmd_set_color() {
|
|
||||||
FastLED.showColor(CRGB(req.color_payload[0], req.color_payload[1], req.color_payload[2]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sg_nfc_cmd_radio_on() {
|
|
||||||
sg_res_init();
|
|
||||||
nfc.setRFField(0x00, 0x01);
|
nfc.setRFField(0x00, 0x01);
|
||||||
u8g2.drawXBM(95, 0, 16, 16, rf_open);
|
u8g2.drawXBM(95, 0, 16, 16, rf_open);
|
||||||
u8g2.sendBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_radio_off() {
|
void nfc_stop_polling() {
|
||||||
sg_res_init();
|
res_init();
|
||||||
nfc.setRFField(0x00, 0x00);
|
nfc.setRFField(0x00, 0x00);
|
||||||
u8g2.drawXBM(95, 0, 16, 16, blank);
|
u8g2.drawXBM(95, 0, 16, 16, blank);
|
||||||
u8g2.sendBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_poll() { //卡号发送
|
void nfc_card_detect() {
|
||||||
|
uint16_t SystemCode;
|
||||||
|
uint8_t bufferLength;
|
||||||
if (!digitalRead(SW3_CARD)) {
|
if (!digitalRead(SW3_CARD)) {
|
||||||
memcpy(res.mifare_uid, mifare_data[0], 0x04);
|
memcpy(res.mifare_uid, mifare_data[0], 0x04);
|
||||||
res.id_len = 0x04;
|
res.id_len = 0x04;
|
||||||
sg_res_init(0x07);
|
res_init(0x07);
|
||||||
res.count = 1;
|
res.count = 1;
|
||||||
res.type = 0x10;
|
res.type = 0x10;
|
||||||
u8g2.drawXBM(113, 0, 16, 16, card);
|
} else if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, res.mifare_uid, &res.id_len) && nfc.getBuffer(&bufferLength)[4] == 0x08) { // Only read cards with sak=0x08
|
||||||
u8g2.sendBuffer();
|
res_init(0x07);
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint16_t SystemCode;
|
|
||||||
if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, res.mifare_uid, &res.id_len)) {
|
|
||||||
sg_res_init(0x07);
|
|
||||||
res.count = 1;
|
res.count = 1;
|
||||||
res.type = 0x10;
|
res.type = 0x10;
|
||||||
} else if (nfc.felica_Polling(0xFFFF, 0x00, res.IDm, res.PMm, &SystemCode, 200) == 1) { //< 0: error
|
} else if (nfc.felica_Polling(0xFFFF, 0x00, res.IDm, res.PMm, &SystemCode, 200) == 1) {
|
||||||
sg_res_init(0x13);
|
res_init(0x13);
|
||||||
res.count = 1;
|
res.count = 1;
|
||||||
res.type = 0x20;
|
res.type = 0x20;
|
||||||
res.id_len = 0x10;
|
res.id_len = 0x10;
|
||||||
} else {
|
} else {
|
||||||
sg_res_init(1);
|
res_init(1);
|
||||||
res.count = 0;
|
res.count = 0;
|
||||||
|
res.status = ERROR_NONE;
|
||||||
u8g2.drawXBM(113, 0, 16, 16, blank);
|
u8g2.drawXBM(113, 0, 16, 16, blank);
|
||||||
u8g2.sendBuffer();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
u8g2.drawXBM(113, 0, 16, 16, card);
|
u8g2.drawXBM(113, 0, 16, 16, card);
|
||||||
u8g2.sendBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_aime_authenticate() {
|
void nfc_mifare_authorize_a() {
|
||||||
sg_res_init();
|
res_init();
|
||||||
if (!digitalRead(SW3_CARD)) {
|
if (!nfc.mifareclassic_AuthenticateBlock(req.uid, 4, req.block_no, 0, KeyA)) {
|
||||||
uint8_t key_block_no = (req.block_no / 4) * 4 + 3;
|
res.status = ERROR_NFCRW_ACCESS_ERROR;
|
||||||
if (memcmp(AimeKey, mifare_data[key_block_no] + 10, 6)) { // Key B
|
|
||||||
res.status = 1;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (nfc.mifareclassic_AuthenticateBlock(req.uid, 4, req.block_no, 1, AimeKey)) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
res.status = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_bana_authenticate() {
|
void nfc_mifare_authorize_b() {
|
||||||
sg_res_init();
|
res_init();
|
||||||
if (!digitalRead(SW3_CARD)) {
|
if (!nfc.mifareclassic_AuthenticateBlock(req.uid, 4, req.block_no, 1, KeyB)) {
|
||||||
uint8_t key_block_no = (req.block_no / 4) * 4 + 3;
|
res.status = ERROR_NFCRW_ACCESS_ERROR;
|
||||||
if (memcmp(BanaKey, mifare_data[key_block_no], 6)) {
|
|
||||||
res.status = 1;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (nfc.mifareclassic_AuthenticateBlock(req.uid, 4, req.block_no, 0, BanaKey)) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
res.status = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_mifare_read_block() { //读取卡扇区数据
|
void nfc_mifare_read() {
|
||||||
|
res_init(0x10);
|
||||||
if (!digitalRead(SW3_CARD)) {
|
if (!digitalRead(SW3_CARD)) {
|
||||||
memcpy(res.block, mifare_data[req.block_no], 16);
|
memcpy(res.block, mifare_data[req.block_no], 16);
|
||||||
sg_res_init(0x10);
|
res_init(0x10);
|
||||||
return;
|
return;
|
||||||
|
} else if (!nfc.mifareclassic_ReadDataBlock(req.block_no, res.block)) {
|
||||||
|
res_init();
|
||||||
|
res.status = ERROR_CARD_DETECT_TIMEOUT; // TODO
|
||||||
}
|
}
|
||||||
if (nfc.mifareclassic_ReadDataBlock(req.block_no, res.block)) {
|
|
||||||
sg_res_init(0x10);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sg_res_init();
|
|
||||||
res.status = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_nfc_cmd_felica_encap() {
|
void nfc_felica_through() {
|
||||||
uint16_t SystemCode;
|
uint16_t SystemCode;
|
||||||
if (nfc.felica_Polling(0xFFFF, 0x01, res.encap_IDm, res.poll_PMm, &SystemCode, 200) == 1) {
|
if (nfc.felica_Polling(0xFFFF, 0x01, res.encap_IDm, res.poll_PMm, &SystemCode, 200) == 1) {
|
||||||
SystemCode = SystemCode >> 8 | SystemCode << 8; //SystemCode,大小端反转注意
|
SystemCode = SystemCode >> 8 | SystemCode << 8;
|
||||||
} else {
|
} else {
|
||||||
sg_res_init();
|
res_init();
|
||||||
res.status = 1;
|
res.status = ERROR_FELICA_ERROR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t code = req.encap_code;
|
uint8_t code = req.encap_code;
|
||||||
res.encap_code = code + 1;
|
res.encap_code = code + 1;
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case FELICA_CMD_POLL:
|
case CMD_FELICA_THROUGH_POLL:
|
||||||
{
|
{
|
||||||
sg_res_init(0x14);
|
res_init(0x14);
|
||||||
res.poll_systemCode[0] = SystemCode;
|
res.poll_systemCode[0] = SystemCode;
|
||||||
res.poll_systemCode[1] = SystemCode >> 8;
|
res.poll_systemCode[1] = SystemCode >> 8;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FELICA_CMD_GET_SYSTEM_CODE:
|
case CMD_FELICA_THROUGH_GET_SYSTEM_CODE:
|
||||||
{
|
{
|
||||||
sg_res_init(0x0D);
|
res_init(0x0D);
|
||||||
res.felica_payload[0] = 0x01; //未知
|
res.felica_payload[0] = 0x01;
|
||||||
res.felica_payload[1] = SystemCode; //SystemCode
|
res.felica_payload[1] = SystemCode;
|
||||||
res.felica_payload[2] = SystemCode >> 8;
|
res.felica_payload[2] = SystemCode >> 8;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FELICA_CMD_NDA_A4:
|
case CMD_FELICA_THROUGH_NDA_A4:
|
||||||
{
|
{
|
||||||
sg_res_init(0x0B);
|
res_init(0x0B);
|
||||||
res.felica_payload[0] = 0x00;
|
res.felica_payload[0] = 0x00;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FELICA_CMD_NDA_06:
|
case CMD_FELICA_THROUGH_READ:
|
||||||
{
|
{
|
||||||
uint16_t serviceCodeList[1] = { (uint16_t)(req.serviceCodeList[1] << 8 | req.serviceCodeList[0]) }; //大小端反转注意
|
uint16_t serviceCodeList[1] = { (uint16_t)(req.serviceCodeList[1] << 8 | req.serviceCodeList[0]) };
|
||||||
for (uint8_t i = 0; i < req.numBlock; i++) {
|
for (uint8_t i = 0; i < req.numBlock; i++) {
|
||||||
uint16_t blockList[1] = { (uint16_t)(req.blockList[i][0] << 8 | req.blockList[i][1]) };
|
uint16_t blockList[1] = { (uint16_t)(req.blockList[i][0] << 8 | req.blockList[i][1]) };
|
||||||
if (nfc.felica_ReadWithoutEncryption(1, serviceCodeList, 1, blockList, res.blockData[i]) != 1) {
|
if (nfc.felica_ReadWithoutEncryption(1, serviceCodeList, 1, blockList, res.blockData[i]) != 1) {
|
||||||
memset(res.blockData[i], 0, 16); //dummy data
|
memset(res.blockData[i], 0, 16); // dummy data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.RW_status[0] = 0;
|
res.RW_status[0] = 0;
|
||||||
res.RW_status[1] = 0;
|
res.RW_status[1] = 0;
|
||||||
res.numBlock = req.numBlock;
|
res.numBlock = req.numBlock;
|
||||||
sg_res_init(0x0D + req.numBlock * 16);
|
res_init(0x0D + req.numBlock * 16);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FELICA_CMD_NDA_08:
|
case CMD_FELICA_THROUGH_WRITE:
|
||||||
{
|
{
|
||||||
sg_res_init(0x0C); //此处应有写入卡,但是不打算实现
|
res_init(0x0C); // WriteWithoutEncryption,ignore
|
||||||
res.RW_status[0] = 0;
|
res.RW_status[0] = 0;
|
||||||
res.RW_status[1] = 0;
|
res.RW_status[1] = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sg_res_init();
|
res_init();
|
||||||
res.status = 1;
|
res.status = ERROR_FELICA_ERROR;
|
||||||
}
|
}
|
||||||
res.encap_len = res.payload_len;
|
res.encap_len = res.payload_len;
|
||||||
}
|
}
|
||||||
|
987
src/PN532.cpp
987
src/PN532.cpp
@ -1,987 +0,0 @@
|
|||||||
/*
|
|
||||||
库代码来自:https://github.com/elechouse/PN532
|
|
||||||
删除了未使用的函数。
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@file PN532.cpp
|
|
||||||
@author Adafruit Industries & Seeed Studio
|
|
||||||
@license BSD
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include "Arduino.h"
|
|
||||||
#include "PN532.h"
|
|
||||||
|
|
||||||
#define HAL(func) (_interface->func)
|
|
||||||
|
|
||||||
PN532::PN532(PN532Interface &interface) {
|
|
||||||
_interface = &interface;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Setups the HW
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void PN532::begin() {
|
|
||||||
HAL(begin)
|
|
||||||
();
|
|
||||||
HAL(wakeup)
|
|
||||||
();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Checks the firmware version of the PN5xx chip
|
|
||||||
|
|
||||||
@returns The chip's firmware version and ID
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
uint32_t PN532::getFirmwareVersion(void) {
|
|
||||||
uint32_t response;
|
|
||||||
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 1)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read data packet
|
|
||||||
int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
|
||||||
if (0 > status) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
response = pn532_packetbuffer[0];
|
|
||||||
response <<= 8;
|
|
||||||
response |= pn532_packetbuffer[1];
|
|
||||||
response <<= 8;
|
|
||||||
response |= pn532_packetbuffer[2];
|
|
||||||
response <<= 8;
|
|
||||||
response |= pn532_packetbuffer[3];
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Read a PN532 register.
|
|
||||||
|
|
||||||
@param reg the 16-bit register address.
|
|
||||||
|
|
||||||
@returns The register value.
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
uint32_t PN532::readRegister(uint16_t reg) {
|
|
||||||
uint32_t response;
|
|
||||||
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_READREGISTER;
|
|
||||||
pn532_packetbuffer[1] = (reg >> 8) & 0xFF;
|
|
||||||
pn532_packetbuffer[2] = reg & 0xFF;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read data packet
|
|
||||||
int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
|
||||||
if (0 > status) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
response = pn532_packetbuffer[0];
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Write to a PN532 register.
|
|
||||||
|
|
||||||
@param reg the 16-bit register address.
|
|
||||||
@param val the 8-bit value to write.
|
|
||||||
|
|
||||||
@returns 0 for failure, 1 for success.
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
uint32_t PN532::writeRegister(uint16_t reg, uint8_t val) {
|
|
||||||
uint32_t response;
|
|
||||||
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_WRITEREGISTER;
|
|
||||||
pn532_packetbuffer[1] = (reg >> 8) & 0xFF;
|
|
||||||
pn532_packetbuffer[2] = reg & 0xFF;
|
|
||||||
pn532_packetbuffer[3] = val;
|
|
||||||
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read data packet
|
|
||||||
int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
|
||||||
if (0 > status) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Configures the SAM (Secure Access Module)
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
bool PN532::SAMConfig(void) {
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
|
|
||||||
pn532_packetbuffer[1] = 0x01; // normal mode;
|
|
||||||
pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
|
|
||||||
pn532_packetbuffer[3] = 0x01; // use IRQ pin!
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 4))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
Sets the MxRtyPassiveActivation uint8_t of the RFConfiguration register
|
|
||||||
|
|
||||||
@param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout
|
|
||||||
after mxRetries
|
|
||||||
|
|
||||||
@returns 1 if everything executed properly, 0 for an error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
bool PN532::setPassiveActivationRetries(uint8_t maxRetries) {
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
|
|
||||||
pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries)
|
|
||||||
pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF)
|
|
||||||
pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01)
|
|
||||||
pn532_packetbuffer[4] = maxRetries;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 5))
|
|
||||||
return 0x0; // no ACK
|
|
||||||
|
|
||||||
return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
Sets the RFon/off uint8_t of the RFConfiguration register
|
|
||||||
|
|
||||||
@param autoRFCA 0x00 No check of the external field before
|
|
||||||
activation
|
|
||||||
|
|
||||||
0x02 Check the external field before
|
|
||||||
activation
|
|
||||||
|
|
||||||
@param rFOnOff 0x00 Switch the RF field off, 0x01 switch the RF
|
|
||||||
field on
|
|
||||||
|
|
||||||
@returns 1 if everything executed properly, 0 for an error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
bool PN532::setRFField(uint8_t autoRFCA, uint8_t rFOnOff) {
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
|
|
||||||
pn532_packetbuffer[1] = 1;
|
|
||||||
pn532_packetbuffer[2] = 0x00 | autoRFCA | rFOnOff;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
|
|
||||||
return 0x0; // command failed
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** ISO14443A Commands ******/
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
Waits for an ISO14443A target to enter the field
|
|
||||||
|
|
||||||
@param cardBaudRate Baud rate of the card
|
|
||||||
@param uid Pointer to the array that will be populated
|
|
||||||
with the card's UID (up to 7 bytes)
|
|
||||||
@param uidLength Pointer to the variable that will hold the
|
|
||||||
length of the card's UID.
|
|
||||||
|
|
||||||
@returns 1 if everything executed properly, 0 for an error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
bool PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout) {
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
|
|
||||||
pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later)
|
|
||||||
pn532_packetbuffer[2] = cardbaudrate;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
|
|
||||||
return 0x0; // command failed
|
|
||||||
}
|
|
||||||
|
|
||||||
// read data packet
|
|
||||||
if (HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) {
|
|
||||||
return 0x0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check some basic stuff
|
|
||||||
/* ISO14443A card response should be in the following format:
|
|
||||||
|
|
||||||
byte Description
|
|
||||||
------------- ------------------------------------------
|
|
||||||
b0 Tags Found
|
|
||||||
b1 Tag Number (only one used in this example)
|
|
||||||
b2..3 SENS_RES
|
|
||||||
b4 SEL_RES
|
|
||||||
b5 NFCID Length
|
|
||||||
b6..NFCIDLen NFCID
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (pn532_packetbuffer[0] != 1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (pn532_packetbuffer[4] != 0x08) // SAK == 0x08
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
uint16_t sens_res = pn532_packetbuffer[2];
|
|
||||||
sens_res <<= 8;
|
|
||||||
sens_res |= pn532_packetbuffer[3];
|
|
||||||
|
|
||||||
/* Card appears to be Mifare Classic */
|
|
||||||
*uidLength = pn532_packetbuffer[5];
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) {
|
|
||||||
uid[i] = pn532_packetbuffer[6 + i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***** Mifare Classic Functions ******/
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
Indicates whether the specified block number is the first block
|
|
||||||
in the sector (block 0 relative to the current sector)
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
bool PN532::mifareclassic_IsFirstBlock(uint32_t uiBlock) {
|
|
||||||
// Test if we are in the small or big sectors
|
|
||||||
if (uiBlock < 128)
|
|
||||||
return ((uiBlock) % 4 == 0);
|
|
||||||
else
|
|
||||||
return ((uiBlock) % 16 == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
Indicates whether the specified block number is the sector trailer
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
bool PN532::mifareclassic_IsTrailerBlock(uint32_t 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
Tries to authenticate a block of memory on a MIFARE card using the
|
|
||||||
INDATAEXCHANGE command. See section 7.3.8 of the PN532 User Manual
|
|
||||||
for more information on sending MIFARE and other commands.
|
|
||||||
|
|
||||||
@param uid Pointer to a byte array containing the card UID
|
|
||||||
@param uidLen The length (in bytes) of the card's UID (Should
|
|
||||||
be 4 for MIFARE Classic)
|
|
||||||
@param blockNumber The block number to authenticate. (0..63 for
|
|
||||||
1KB cards, and 0..255 for 4KB cards).
|
|
||||||
@param keyNumber Which key type to use during authentication
|
|
||||||
(0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
|
|
||||||
@param keyData Pointer to a byte array containing the 6 bytes
|
|
||||||
key value
|
|
||||||
|
|
||||||
@returns 1 if everything executed properly, 0 for an error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
uint8_t PN532::mifareclassic_AuthenticateBlock(uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) {
|
|
||||||
uint8_t i;
|
|
||||||
|
|
||||||
// Hang on to the key and uid data
|
|
||||||
memcpy(_key, keyData, 6);
|
|
||||||
memcpy(_uid, uid, uidLen);
|
|
||||||
_uidLen = uidLen;
|
|
||||||
|
|
||||||
// Prepare the authentication command //
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */
|
|
||||||
pn532_packetbuffer[1] = 1; /* Max card numbers */
|
|
||||||
pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
|
|
||||||
pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */
|
|
||||||
memcpy(pn532_packetbuffer + 4, _key, 6);
|
|
||||||
for (i = 0; i < _uidLen; i++) {
|
|
||||||
pn532_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 10 + _uidLen))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Read the response packet
|
|
||||||
HAL(readResponse)
|
|
||||||
(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
|
||||||
|
|
||||||
// Check if the response is valid and we are authenticated???
|
|
||||||
// for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
|
|
||||||
// Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
|
|
||||||
if (pn532_packetbuffer[0] != 0x00) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
Tries to read an entire 16-bytes data block at the specified block
|
|
||||||
address.
|
|
||||||
|
|
||||||
@param blockNumber The block number to authenticate. (0..63 for
|
|
||||||
1KB cards, and 0..255 for 4KB cards).
|
|
||||||
@param data Pointer to the byte array that will hold the
|
|
||||||
retrieved data (if any)
|
|
||||||
|
|
||||||
@returns 1 if everything executed properly, 0 for an error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
uint8_t PN532::mifareclassic_ReadDataBlock(uint8_t blockNumber, uint8_t *data) {
|
|
||||||
|
|
||||||
/* Prepare the command */
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
|
||||||
pn532_packetbuffer[1] = 1; /* Card number */
|
|
||||||
pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
|
|
||||||
pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
|
||||||
|
|
||||||
/* Send the command */
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 4)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the response packet */
|
|
||||||
HAL(readResponse)
|
|
||||||
(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
|
||||||
|
|
||||||
/* If byte 8 isn't 0x00 we probably have an error */
|
|
||||||
if (pn532_packetbuffer[0] != 0x00) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the 16 data bytes to the output buffer */
|
|
||||||
/* Block content starts at byte 9 of a valid response */
|
|
||||||
memcpy(data, pn532_packetbuffer + 1, 16);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
Tries to write an entire 16-bytes data block at the specified block
|
|
||||||
address.
|
|
||||||
|
|
||||||
@param blockNumber The block number to authenticate. (0..63 for
|
|
||||||
1KB cards, and 0..255 for 4KB cards).
|
|
||||||
@param data The byte array that contains the data to write.
|
|
||||||
|
|
||||||
@returns 1 if everything executed properly, 0 for an error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
uint8_t PN532::mifareclassic_WriteDataBlock(uint8_t blockNumber, uint8_t *data) {
|
|
||||||
/* Prepare the first command */
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
|
||||||
pn532_packetbuffer[1] = 1; /* Card number */
|
|
||||||
pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */
|
|
||||||
pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
|
||||||
memcpy(pn532_packetbuffer + 4, data, 16); /* Data Payload */
|
|
||||||
|
|
||||||
/* Send the command */
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 20)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the response packet */
|
|
||||||
return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Exchanges an APDU with the currently inlisted peer
|
|
||||||
|
|
||||||
@param send Pointer to data to send
|
|
||||||
@param sendLength Length of the data to send
|
|
||||||
@param response Pointer to response data
|
|
||||||
@param responseLength Pointer to the response data length
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
bool PN532::inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength) {
|
|
||||||
uint8_t i;
|
|
||||||
|
|
||||||
pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE;
|
|
||||||
pn532_packetbuffer[1] = inListedTag;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 2, send, sendLength)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t status = HAL(readResponse)(response, *responseLength, 1000);
|
|
||||||
if (status < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((response[0] & 0x3f) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t length = status;
|
|
||||||
length -= 1;
|
|
||||||
|
|
||||||
if (length > *responseLength) {
|
|
||||||
length = *responseLength; // silent truncation...
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < length; i++) {
|
|
||||||
response[i] = response[i + 1];
|
|
||||||
}
|
|
||||||
*responseLength = length;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief 'InLists' a passive target. PN532 acting as reader/initiator,
|
|
||||||
peer acting as card/responder.
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
bool PN532::inListPassiveTarget() {
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
|
|
||||||
pn532_packetbuffer[1] = 1;
|
|
||||||
pn532_packetbuffer[2] = 0;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 3)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 30000);
|
|
||||||
if (status < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pn532_packetbuffer[0] != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inListedTag = pn532_packetbuffer[1];
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int8_t PN532::tgInitAsTarget(const uint8_t *command, const uint8_t len, const uint16_t timeout) {
|
|
||||||
|
|
||||||
int8_t status = HAL(writeCommand)(command, len);
|
|
||||||
if (status < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout);
|
|
||||||
if (status > 0) {
|
|
||||||
return 1;
|
|
||||||
} else if (PN532_TIMEOUT == status) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Peer to Peer
|
|
||||||
*/
|
|
||||||
int8_t PN532::tgInitAsTarget(uint16_t timeout) {
|
|
||||||
const uint8_t command[] = {
|
|
||||||
PN532_COMMAND_TGINITASTARGET,
|
|
||||||
0,
|
|
||||||
0x00, 0x00, //SENS_RES
|
|
||||||
0x00, 0x00, 0x00, //NFCID1
|
|
||||||
0x40, //SEL_RES
|
|
||||||
|
|
||||||
0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, // POL_RES
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xFF, 0xFF,
|
|
||||||
|
|
||||||
0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, //NFCID3t: Change this to desired value
|
|
||||||
|
|
||||||
0x06, 0x46, 0x66, 0x6D, 0x01, 0x01, 0x10, 0x00 // LLCP magic number and version parameter
|
|
||||||
};
|
|
||||||
return tgInitAsTarget(command, sizeof(command), timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t PN532::tgGetData(uint8_t *buf, uint8_t len) {
|
|
||||||
buf[0] = PN532_COMMAND_TGGETDATA;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(buf, 1)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t status = HAL(readResponse)(buf, len, 3000);
|
|
||||||
if (0 >= status) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t length = status - 1;
|
|
||||||
|
|
||||||
|
|
||||||
if (buf[0] != 0) {
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < length; i++) {
|
|
||||||
buf[i] = buf[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PN532::tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) {
|
|
||||||
if (hlen > (sizeof(pn532_packetbuffer) - 1)) {
|
|
||||||
if ((body != 0) || (header == pn532_packetbuffer)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA;
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 1, header, hlen)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int8_t i = hlen - 1; i >= 0; i--) {
|
|
||||||
pn532_packetbuffer[i + 1] = header[i];
|
|
||||||
}
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_TGSETDATA;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, hlen + 1, body, blen)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 > HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 3000)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != pn532_packetbuffer[0]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t PN532::inRelease(const uint8_t relevantTarget) {
|
|
||||||
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_INRELEASE;
|
|
||||||
pn532_packetbuffer[1] = relevantTarget;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 2)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read data packet
|
|
||||||
return HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***** FeliCa Functions ******/
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Poll FeliCa card. PN532 acting as reader/initiator,
|
|
||||||
peer acting as card/responder.
|
|
||||||
@param[in] systemCode Designation of System Code. When sending FFFFh as System Code,
|
|
||||||
all FeliCa cards can return response.
|
|
||||||
@param[in] requestCode Designation of Request Data as follows:
|
|
||||||
00h: No Request
|
|
||||||
01h: System Code request (to acquire System Code of the card)
|
|
||||||
02h: Communication perfomance request
|
|
||||||
@param[out] idm IDm of the card (8 bytes)
|
|
||||||
@param[out] pmm PMm of the card (8 bytes)
|
|
||||||
@param[out] systemCodeResponse System Code of the card (Optional, 2bytes)
|
|
||||||
@return = 1: A FeliCa card has detected
|
|
||||||
= 0: No card has detected
|
|
||||||
< 0: error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
int8_t PN532::felica_Polling(uint16_t systemCode, uint8_t requestCode, uint8_t *idm, uint8_t *pmm, uint16_t *systemCodeResponse, uint16_t timeout) {
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
|
|
||||||
pn532_packetbuffer[1] = 1;
|
|
||||||
pn532_packetbuffer[2] = 1;
|
|
||||||
pn532_packetbuffer[3] = FELICA_CMD_POLLING;
|
|
||||||
pn532_packetbuffer[4] = (systemCode >> 8) & 0xFF;
|
|
||||||
pn532_packetbuffer[5] = systemCode & 0xFF;
|
|
||||||
pn532_packetbuffer[6] = requestCode;
|
|
||||||
pn532_packetbuffer[7] = 0;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 8)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t status = HAL(readResponse)(pn532_packetbuffer, 22, timeout);
|
|
||||||
if (status < 0) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check NbTg (pn532_packetbuffer[7])
|
|
||||||
if (pn532_packetbuffer[0] == 0) {
|
|
||||||
return 0;
|
|
||||||
} else if (pn532_packetbuffer[0] != 1) {
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
inListedTag = pn532_packetbuffer[1];
|
|
||||||
|
|
||||||
// length check
|
|
||||||
uint8_t responseLength = pn532_packetbuffer[2];
|
|
||||||
if (responseLength != 18 && responseLength != 20) {
|
|
||||||
return -4;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t i;
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
idm[i] = pn532_packetbuffer[4 + i];
|
|
||||||
_felicaIDm[i] = pn532_packetbuffer[4 + i];
|
|
||||||
pmm[i] = pn532_packetbuffer[12 + i];
|
|
||||||
_felicaPMm[i] = pn532_packetbuffer[12 + i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (responseLength == 20) {
|
|
||||||
*systemCodeResponse = (uint16_t)((pn532_packetbuffer[20] << 8) + pn532_packetbuffer[21]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Sends FeliCa command to the currently inlisted peer
|
|
||||||
|
|
||||||
@param[in] command FeliCa command packet. (e.g. 00 FF FF 00 00 for Polling command)
|
|
||||||
@param[in] commandlength Length of the FeliCa command packet. (e.g. 0x05 for above Polling command )
|
|
||||||
@param[out] response FeliCa response packet. (e.g. 01 NFCID2(8 bytes) PAD(8 bytes) for Polling response)
|
|
||||||
@param[out] responselength Length of the FeliCa response packet. (e.g. 0x11 for above Polling command )
|
|
||||||
@return = 1: Success
|
|
||||||
< 0: error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
int8_t PN532::felica_SendCommand(const uint8_t *command, uint8_t commandlength, uint8_t *response, uint8_t *responseLength) {
|
|
||||||
if (commandlength > 0xFE) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pn532_packetbuffer[0] = 0x40; // PN532_COMMAND_INDATAEXCHANGE;
|
|
||||||
pn532_packetbuffer[1] = inListedTag;
|
|
||||||
pn532_packetbuffer[2] = commandlength + 1;
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 3, command, commandlength)) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait card response
|
|
||||||
int16_t status = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 200);
|
|
||||||
if (status < 0) {
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check status (pn532_packetbuffer[0])
|
|
||||||
if ((pn532_packetbuffer[0] & 0x3F) != 0) {
|
|
||||||
return -4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// length check
|
|
||||||
*responseLength = pn532_packetbuffer[1] - 1;
|
|
||||||
if ((status - 2) != *responseLength) {
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(response, &pn532_packetbuffer[2], *responseLength);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Sends FeliCa Request Service command
|
|
||||||
|
|
||||||
@param[in] numNode length of the nodeCodeList
|
|
||||||
@param[in] nodeCodeList Node codes(Big Endian)
|
|
||||||
@param[out] keyVersions Key Version of each Node (Big Endian)
|
|
||||||
@return = 1: Success
|
|
||||||
< 0: error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
int8_t PN532::felica_RequestService(uint8_t numNode, uint16_t *nodeCodeList, uint16_t *keyVersions) {
|
|
||||||
if (numNode > FELICA_REQ_SERVICE_MAX_NODE_NUM) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t i, j = 0;
|
|
||||||
uint8_t cmdLen = 1 + 8 + 1 + 2 * numNode;
|
|
||||||
uint8_t cmd[cmdLen];
|
|
||||||
cmd[j++] = FELICA_CMD_REQUEST_SERVICE;
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
cmd[j++] = _felicaIDm[i];
|
|
||||||
}
|
|
||||||
cmd[j++] = numNode;
|
|
||||||
for (i = 0; i < numNode; ++i) {
|
|
||||||
cmd[j++] = nodeCodeList[i] & 0xFF;
|
|
||||||
cmd[j++] = (nodeCodeList[i] >> 8) & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t response[10 + 2 * numNode];
|
|
||||||
uint8_t responseLength;
|
|
||||||
|
|
||||||
if (felica_SendCommand(cmd, cmdLen, response, &responseLength) != 1) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// length check
|
|
||||||
if (responseLength != 10 + 2 * numNode) {
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < numNode; i++) {
|
|
||||||
keyVersions[i] = (uint16_t)(response[10 + i * 2] + (response[10 + i * 2 + 1] << 8));
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Sends FeliCa Request Service command
|
|
||||||
|
|
||||||
@param[out] mode Current Mode of the card
|
|
||||||
@return = 1: Success
|
|
||||||
< 0: error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
int8_t PN532::felica_RequestResponse(uint8_t *mode) {
|
|
||||||
uint8_t cmd[9];
|
|
||||||
cmd[0] = FELICA_CMD_REQUEST_RESPONSE;
|
|
||||||
memcpy(&cmd[1], _felicaIDm, 8);
|
|
||||||
|
|
||||||
uint8_t response[10];
|
|
||||||
uint8_t responseLength;
|
|
||||||
if (felica_SendCommand(cmd, 9, response, &responseLength) != 1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// length check
|
|
||||||
if (responseLength != 10) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
*mode = response[9];
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Sends FeliCa Read Without Encryption command
|
|
||||||
|
|
||||||
@param[in] numService Length of the serviceCodeList
|
|
||||||
@param[in] serviceCodeList Service Code List (Big Endian)
|
|
||||||
@param[in] numBlock Length of the blockList
|
|
||||||
@param[in] blockList Block List (Big Endian, This API only accepts 2-byte block list element)
|
|
||||||
@param[out] blockData Block Data
|
|
||||||
@return = 1: Success
|
|
||||||
< 0: error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
int8_t PN532::felica_ReadWithoutEncryption(uint8_t numService, const uint16_t *serviceCodeList, uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16]) {
|
|
||||||
if (numService > FELICA_READ_MAX_SERVICE_NUM) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (numBlock > FELICA_READ_MAX_BLOCK_NUM) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t i, j = 0, k;
|
|
||||||
uint8_t cmdLen = 1 + 8 + 1 + 2 * numService + 1 + 2 * numBlock;
|
|
||||||
uint8_t cmd[cmdLen];
|
|
||||||
cmd[j++] = FELICA_CMD_READ_WITHOUT_ENCRYPTION;
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
cmd[j++] = _felicaIDm[i];
|
|
||||||
}
|
|
||||||
cmd[j++] = numService;
|
|
||||||
for (i = 0; i < numService; ++i) {
|
|
||||||
cmd[j++] = serviceCodeList[i] & 0xFF;
|
|
||||||
cmd[j++] = (serviceCodeList[i] >> 8) & 0xff;
|
|
||||||
}
|
|
||||||
cmd[j++] = numBlock;
|
|
||||||
for (i = 0; i < numBlock; ++i) {
|
|
||||||
cmd[j++] = (blockList[i] >> 8) & 0xFF;
|
|
||||||
cmd[j++] = blockList[i] & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t response[12 + 16 * numBlock];
|
|
||||||
uint8_t responseLength;
|
|
||||||
if (felica_SendCommand(cmd, cmdLen, response, &responseLength) != 1) {
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// length check
|
|
||||||
if (responseLength != 12 + 16 * numBlock) {
|
|
||||||
return -4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// status flag check
|
|
||||||
if (response[9] != 0 || response[10] != 0) {
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
k = 12;
|
|
||||||
for (i = 0; i < numBlock; i++) {
|
|
||||||
for (j = 0; j < 16; j++) {
|
|
||||||
blockData[i][j] = response[k++];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Sends FeliCa Write Without Encryption command
|
|
||||||
|
|
||||||
@param[in] numService Length of the serviceCodeList
|
|
||||||
@param[in] serviceCodeList Service Code List (Big Endian)
|
|
||||||
@param[in] numBlock Length of the blockList
|
|
||||||
@param[in] blockList Block List (Big Endian, This API only accepts 2-byte block list element)
|
|
||||||
@param[in] blockData Block Data (each Block has 16 bytes)
|
|
||||||
@return = 1: Success
|
|
||||||
< 0: error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
int8_t PN532::felica_WriteWithoutEncryption(uint8_t numService, const uint16_t *serviceCodeList, uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16]) {
|
|
||||||
if (numService > FELICA_WRITE_MAX_SERVICE_NUM) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (numBlock > FELICA_WRITE_MAX_BLOCK_NUM) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t i, j = 0, k;
|
|
||||||
uint8_t cmdLen = 1 + 8 + 1 + 2 * numService + 1 + 2 * numBlock + 16 * numBlock;
|
|
||||||
uint8_t cmd[cmdLen];
|
|
||||||
cmd[j++] = FELICA_CMD_WRITE_WITHOUT_ENCRYPTION;
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
cmd[j++] = _felicaIDm[i];
|
|
||||||
}
|
|
||||||
cmd[j++] = numService;
|
|
||||||
for (i = 0; i < numService; ++i) {
|
|
||||||
cmd[j++] = serviceCodeList[i] & 0xFF;
|
|
||||||
cmd[j++] = (serviceCodeList[i] >> 8) & 0xff;
|
|
||||||
}
|
|
||||||
cmd[j++] = numBlock;
|
|
||||||
for (i = 0; i < numBlock; ++i) {
|
|
||||||
cmd[j++] = (blockList[i] >> 8) & 0xFF;
|
|
||||||
cmd[j++] = blockList[i] & 0xff;
|
|
||||||
}
|
|
||||||
for (i = 0; i < numBlock; ++i) {
|
|
||||||
for (k = 0; k < 16; k++) {
|
|
||||||
cmd[j++] = blockData[i][k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t response[11];
|
|
||||||
uint8_t responseLength;
|
|
||||||
if (felica_SendCommand(cmd, cmdLen, response, &responseLength) != 1) {
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// length check
|
|
||||||
if (responseLength != 11) {
|
|
||||||
return -4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// status flag check
|
|
||||||
if (response[9] != 0 || response[10] != 0) {
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Sends FeliCa Request System Code command
|
|
||||||
|
|
||||||
@param[out] numSystemCode Length of the systemCodeList
|
|
||||||
@param[out] systemCodeList System Code list (Array length should longer than 16)
|
|
||||||
@return = 1: Success
|
|
||||||
< 0: error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
int8_t PN532::felica_RequestSystemCode(uint8_t *numSystemCode, uint16_t *systemCodeList) {
|
|
||||||
uint8_t cmd[9];
|
|
||||||
cmd[0] = FELICA_CMD_REQUEST_SYSTEM_CODE;
|
|
||||||
memcpy(&cmd[1], _felicaIDm, 8);
|
|
||||||
|
|
||||||
uint8_t response[10 + 2 * 16];
|
|
||||||
uint8_t responseLength;
|
|
||||||
if (felica_SendCommand(cmd, 9, response, &responseLength) != 1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*numSystemCode = response[9];
|
|
||||||
|
|
||||||
// length check
|
|
||||||
if (responseLength < 10 + 2 * *numSystemCode) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t i;
|
|
||||||
for (i = 0; i < *numSystemCode; i++) {
|
|
||||||
systemCodeList[i] = (uint16_t)((response[10 + i * 2] << 8) + response[10 + i * 2 + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Release FeliCa card
|
|
||||||
@return = 1: Success
|
|
||||||
< 0: error
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
int8_t PN532::felica_Release() {
|
|
||||||
// InRelease
|
|
||||||
pn532_packetbuffer[0] = PN532_COMMAND_INRELEASE;
|
|
||||||
pn532_packetbuffer[1] = 0x00; // All target
|
|
||||||
|
|
||||||
if (HAL(writeCommand)(pn532_packetbuffer, 2)) {
|
|
||||||
return -1; // no ACK
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait card response
|
|
||||||
int16_t frameLength = HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer), 1000);
|
|
||||||
if (frameLength < 0) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check status (pn532_packetbuffer[0])
|
|
||||||
if ((pn532_packetbuffer[0] & 0x3F) != 0) {
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
153
src/PN532.h
153
src/PN532.h
@ -1,153 +0,0 @@
|
|||||||
/*
|
|
||||||
库代码来自:https://github.com/elechouse/PN532
|
|
||||||
删除了未使用的函数。
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@file PN532.h
|
|
||||||
@author Adafruit Industries & Seeed Studio
|
|
||||||
@license BSD
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#ifndef __PN532_H__
|
|
||||||
#define __PN532_H__
|
|
||||||
|
|
||||||
#include "PN532Interface.h"
|
|
||||||
|
|
||||||
// PN532 Commands
|
|
||||||
#define PN532_COMMAND_DIAGNOSE (0x00)
|
|
||||||
#define PN532_COMMAND_GETFIRMWAREVERSION (0x02)
|
|
||||||
#define PN532_COMMAND_GETGENERALSTATUS (0x04)
|
|
||||||
#define PN532_COMMAND_READREGISTER (0x06)
|
|
||||||
#define PN532_COMMAND_WRITEREGISTER (0x08)
|
|
||||||
#define PN532_COMMAND_READGPIO (0x0C)
|
|
||||||
#define PN532_COMMAND_WRITEGPIO (0x0E)
|
|
||||||
#define PN532_COMMAND_SETSERIALBAUDRATE (0x10)
|
|
||||||
#define PN532_COMMAND_SETPARAMETERS (0x12)
|
|
||||||
#define PN532_COMMAND_SAMCONFIGURATION (0x14)
|
|
||||||
#define PN532_COMMAND_POWERDOWN (0x16)
|
|
||||||
#define PN532_COMMAND_RFCONFIGURATION (0x32)
|
|
||||||
#define PN532_COMMAND_RFREGULATIONTEST (0x58)
|
|
||||||
#define PN532_COMMAND_INJUMPFORDEP (0x56)
|
|
||||||
#define PN532_COMMAND_INJUMPFORPSL (0x46)
|
|
||||||
#define PN532_COMMAND_INLISTPASSIVETARGET (0x4A)
|
|
||||||
#define PN532_COMMAND_INATR (0x50)
|
|
||||||
#define PN532_COMMAND_INPSL (0x4E)
|
|
||||||
#define PN532_COMMAND_INDATAEXCHANGE (0x40)
|
|
||||||
#define PN532_COMMAND_INCOMMUNICATETHRU (0x42)
|
|
||||||
#define PN532_COMMAND_INDESELECT (0x44)
|
|
||||||
#define PN532_COMMAND_INRELEASE (0x52)
|
|
||||||
#define PN532_COMMAND_INSELECT (0x54)
|
|
||||||
#define PN532_COMMAND_INAUTOPOLL (0x60)
|
|
||||||
#define PN532_COMMAND_TGINITASTARGET (0x8C)
|
|
||||||
#define PN532_COMMAND_TGSETGENERALBYTES (0x92)
|
|
||||||
#define PN532_COMMAND_TGGETDATA (0x86)
|
|
||||||
#define PN532_COMMAND_TGSETDATA (0x8E)
|
|
||||||
#define PN532_COMMAND_TGSETMETADATA (0x94)
|
|
||||||
#define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88)
|
|
||||||
#define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90)
|
|
||||||
#define PN532_COMMAND_TGGETTARGETSTATUS (0x8A)
|
|
||||||
|
|
||||||
#define PN532_RESPONSE_INDATAEXCHANGE (0x41)
|
|
||||||
#define PN532_RESPONSE_INLISTPASSIVETARGET (0x4B)
|
|
||||||
|
|
||||||
|
|
||||||
#define PN532_MIFARE_ISO14443A (0x00)
|
|
||||||
|
|
||||||
// Mifare Commands
|
|
||||||
#define MIFARE_CMD_AUTH_A (0x60)
|
|
||||||
#define MIFARE_CMD_AUTH_B (0x61)
|
|
||||||
#define MIFARE_CMD_READ (0x30)
|
|
||||||
#define MIFARE_CMD_WRITE (0xA0)
|
|
||||||
#define MIFARE_CMD_WRITE_ULTRALIGHT (0xA2)
|
|
||||||
#define MIFARE_CMD_TRANSFER (0xB0)
|
|
||||||
#define MIFARE_CMD_DECREMENT (0xC0)
|
|
||||||
#define MIFARE_CMD_INCREMENT (0xC1)
|
|
||||||
#define MIFARE_CMD_STORE (0xC2)
|
|
||||||
|
|
||||||
// FeliCa Commands
|
|
||||||
#define FELICA_CMD_POLLING (0x00)
|
|
||||||
#define FELICA_CMD_REQUEST_SERVICE (0x02)
|
|
||||||
#define FELICA_CMD_REQUEST_RESPONSE (0x04)
|
|
||||||
#define FELICA_CMD_READ_WITHOUT_ENCRYPTION (0x06)
|
|
||||||
#define FELICA_CMD_WRITE_WITHOUT_ENCRYPTION (0x08)
|
|
||||||
#define FELICA_CMD_REQUEST_SYSTEM_CODE (0x0C)
|
|
||||||
|
|
||||||
// FeliCa consts
|
|
||||||
#define FELICA_READ_MAX_SERVICE_NUM 16
|
|
||||||
#define FELICA_READ_MAX_BLOCK_NUM 12 // for typical FeliCa card
|
|
||||||
#define FELICA_WRITE_MAX_SERVICE_NUM 16
|
|
||||||
#define FELICA_WRITE_MAX_BLOCK_NUM 10 // for typical FeliCa card
|
|
||||||
#define FELICA_REQ_SERVICE_MAX_NODE_NUM 32
|
|
||||||
|
|
||||||
class PN532 {
|
|
||||||
public:
|
|
||||||
PN532(PN532Interface &interface);
|
|
||||||
|
|
||||||
void begin(void);
|
|
||||||
|
|
||||||
// Generic PN532 functions
|
|
||||||
bool SAMConfig(void);
|
|
||||||
uint32_t getFirmwareVersion(void);
|
|
||||||
uint32_t readRegister(uint16_t reg);
|
|
||||||
uint32_t writeRegister(uint16_t reg, uint8_t val);
|
|
||||||
bool setPassiveActivationRetries(uint8_t maxRetries);
|
|
||||||
bool setRFField(uint8_t autoRFCA, uint8_t rFOnOff);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Init PN532 as a target
|
|
||||||
* @param timeout max time to wait, 0 means no timeout
|
|
||||||
* @return > 0 success
|
|
||||||
* = 0 timeout
|
|
||||||
* < 0 failed
|
|
||||||
*/
|
|
||||||
int8_t tgInitAsTarget(uint16_t timeout = 0);
|
|
||||||
int8_t tgInitAsTarget(const uint8_t *command, const uint8_t len, const uint16_t timeout = 0);
|
|
||||||
|
|
||||||
int16_t tgGetData(uint8_t *buf, uint8_t len);
|
|
||||||
bool tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
|
|
||||||
|
|
||||||
int16_t inRelease(const uint8_t relevantTarget = 0);
|
|
||||||
|
|
||||||
// ISO14443A functions
|
|
||||||
bool inListPassiveTarget();
|
|
||||||
bool readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 1000);
|
|
||||||
bool inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength);
|
|
||||||
|
|
||||||
// Mifare Classic functions
|
|
||||||
bool mifareclassic_IsFirstBlock(uint32_t uiBlock);
|
|
||||||
bool mifareclassic_IsTrailerBlock(uint32_t uiBlock);
|
|
||||||
uint8_t mifareclassic_AuthenticateBlock(uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData);
|
|
||||||
uint8_t mifareclassic_ReadDataBlock(uint8_t blockNumber, uint8_t *data);
|
|
||||||
uint8_t mifareclassic_WriteDataBlock(uint8_t blockNumber, uint8_t *data);
|
|
||||||
|
|
||||||
// FeliCa Functions
|
|
||||||
int8_t felica_Polling(uint16_t systemCode, uint8_t requestCode, uint8_t *idm, uint8_t *pmm, uint16_t *systemCodeResponse, uint16_t timeout = 1000);
|
|
||||||
int8_t felica_SendCommand(const uint8_t *command, uint8_t commandlength, uint8_t *response, uint8_t *responseLength);
|
|
||||||
int8_t felica_RequestService(uint8_t numNode, uint16_t *nodeCodeList, uint16_t *keyVersions);
|
|
||||||
int8_t felica_RequestResponse(uint8_t *mode);
|
|
||||||
int8_t felica_ReadWithoutEncryption(uint8_t numService, const uint16_t *serviceCodeList, uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16]);
|
|
||||||
int8_t felica_WriteWithoutEncryption(uint8_t numService, const uint16_t *serviceCodeList, uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16]);
|
|
||||||
int8_t felica_RequestSystemCode(uint8_t *numSystemCode, uint16_t *systemCodeList);
|
|
||||||
int8_t felica_Release();
|
|
||||||
|
|
||||||
uint8_t *getBuffer(uint8_t *len) {
|
|
||||||
*len = sizeof(pn532_packetbuffer) - 4;
|
|
||||||
return pn532_packetbuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t _uid[7]; // ISO14443A uid
|
|
||||||
uint8_t _uidLen; // uid len
|
|
||||||
uint8_t _key[6]; // Mifare Classic key
|
|
||||||
uint8_t inListedTag; // Tg number of inlisted tag.
|
|
||||||
uint8_t _felicaIDm[8]; // FeliCa IDm (NFCID2)
|
|
||||||
uint8_t _felicaPMm[8]; // FeliCa PMm (PAD)
|
|
||||||
|
|
||||||
uint8_t pn532_packetbuffer[64];
|
|
||||||
|
|
||||||
PN532Interface *_interface;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
库代码来自:https://github.com/elechouse/PN532
|
|
||||||
删除了未使用的函数。
|
|
||||||
*/
|
|
||||||
#ifndef __PN532_INTERFACE_H__
|
|
||||||
#define __PN532_INTERFACE_H__
|
|
||||||
|
|
||||||
#define PN532_PREAMBLE (0x00)
|
|
||||||
#define PN532_STARTCODE1 (0x00)
|
|
||||||
#define PN532_STARTCODE2 (0xFF)
|
|
||||||
#define PN532_POSTAMBLE (0x00)
|
|
||||||
|
|
||||||
#define PN532_HOSTTOPN532 (0xD4)
|
|
||||||
#define PN532_PN532TOHOST (0xD5)
|
|
||||||
|
|
||||||
#define PN532_ACK_WAIT_TIME (10) // ms, timeout of waiting for ACK
|
|
||||||
|
|
||||||
#define PN532_INVALID_ACK (-1)
|
|
||||||
#define PN532_TIMEOUT (-2)
|
|
||||||
#define PN532_INVALID_FRAME (-3)
|
|
||||||
#define PN532_NO_SPACE (-4)
|
|
||||||
|
|
||||||
#define REVERSE_BITS_ORDER(b) \
|
|
||||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; \
|
|
||||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2; \
|
|
||||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1
|
|
||||||
|
|
||||||
class PN532Interface {
|
|
||||||
public:
|
|
||||||
virtual void begin() = 0;
|
|
||||||
virtual void wakeup() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief write a command and check ack
|
|
||||||
* @param header packet header
|
|
||||||
* @param hlen length of header
|
|
||||||
* @param body packet body
|
|
||||||
* @param blen length of body
|
|
||||||
* @return 0 success
|
|
||||||
* not 0 failed
|
|
||||||
*/
|
|
||||||
virtual int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief read the response of a command, strip prefix and suffix
|
|
||||||
* @param buf to contain the response data
|
|
||||||
* @param len lenght to read
|
|
||||||
* @param timeout max time to wait, 0 means no timeout
|
|
||||||
* @return >=0 length of response without prefix and suffix
|
|
||||||
* <0 failed to read response
|
|
||||||
*/
|
|
||||||
virtual int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 1000) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,186 +0,0 @@
|
|||||||
/*
|
|
||||||
库代码来自:https://github.com/elechouse/PN532
|
|
||||||
删除了未使用的函数。
|
|
||||||
*/
|
|
||||||
#include "PN532_SPI.h"
|
|
||||||
#include "Arduino.h"
|
|
||||||
|
|
||||||
#define STATUS_READ 2
|
|
||||||
#define DATA_WRITE 1
|
|
||||||
#define DATA_READ 3
|
|
||||||
|
|
||||||
PN532_SPI::PN532_SPI(SPIClass &spi, uint8_t ss) {
|
|
||||||
command = 0;
|
|
||||||
_spi = &spi;
|
|
||||||
_ss = ss;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PN532_SPI::begin() {
|
|
||||||
pinMode(_ss, OUTPUT);
|
|
||||||
|
|
||||||
_spi->begin();
|
|
||||||
_spi->setDataMode(SPI_MODE0); // PN532 only supports mode0
|
|
||||||
_spi->setBitOrder(LSBFIRST);
|
|
||||||
#ifndef __SAM3X8E__
|
|
||||||
_spi->setClockDivider(SPI_CLOCK_DIV8); // set clock 2MHz(max: 5MHz)
|
|
||||||
#else
|
|
||||||
/** DUE spi library does not support SPI_CLOCK_DIV8 macro */
|
|
||||||
_spi->setClockDivider(42); // set clock 2MHz(max: 5MHz)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PN532_SPI::wakeup() {
|
|
||||||
digitalWrite(_ss, LOW);
|
|
||||||
delay(2);
|
|
||||||
digitalWrite(_ss, HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int8_t PN532_SPI::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) {
|
|
||||||
command = header[0];
|
|
||||||
writeFrame(header, hlen, body, blen);
|
|
||||||
|
|
||||||
uint8_t timeout = PN532_ACK_WAIT_TIME;
|
|
||||||
while (!isReady()) {
|
|
||||||
delay(1);
|
|
||||||
timeout--;
|
|
||||||
if (0 == timeout) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (readAckFrame()) {
|
|
||||||
return PN532_INVALID_ACK;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t PN532_SPI::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout) {
|
|
||||||
uint16_t time = 0;
|
|
||||||
while (!isReady()) {
|
|
||||||
delay(1);
|
|
||||||
time++;
|
|
||||||
if (timeout > 0 && time > timeout) {
|
|
||||||
return PN532_TIMEOUT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
digitalWrite(_ss, LOW);
|
|
||||||
delay(1);
|
|
||||||
|
|
||||||
int16_t result;
|
|
||||||
do {
|
|
||||||
write(DATA_READ);
|
|
||||||
|
|
||||||
if (0x00 != read() || // PREAMBLE
|
|
||||||
0x00 != read() || // STARTCODE1
|
|
||||||
0xFF != read() // STARTCODE2
|
|
||||||
) {
|
|
||||||
|
|
||||||
result = PN532_INVALID_FRAME;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t length = read();
|
|
||||||
if (0 != (uint8_t)(length + read())) { // checksum of length
|
|
||||||
result = PN532_INVALID_FRAME;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t cmd = command + 1; // response command
|
|
||||||
if (PN532_PN532TOHOST != read() || (cmd) != read()) {
|
|
||||||
result = PN532_INVALID_FRAME;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
length -= 2;
|
|
||||||
if (length > len) {
|
|
||||||
for (uint8_t i = 0; i < length; i++) {
|
|
||||||
}
|
|
||||||
read();
|
|
||||||
read();
|
|
||||||
result = PN532_NO_SPACE; // not enough space
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t sum = PN532_PN532TOHOST + cmd;
|
|
||||||
for (uint8_t i = 0; i < length; i++) {
|
|
||||||
buf[i] = read();
|
|
||||||
sum += buf[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t checksum = read();
|
|
||||||
if (0 != (uint8_t)(sum + checksum)) {
|
|
||||||
result = PN532_INVALID_FRAME;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
read(); // POSTAMBLE
|
|
||||||
|
|
||||||
result = length;
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
digitalWrite(_ss, HIGH);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PN532_SPI::isReady() {
|
|
||||||
digitalWrite(_ss, LOW);
|
|
||||||
|
|
||||||
write(STATUS_READ);
|
|
||||||
uint8_t status = read() & 1;
|
|
||||||
digitalWrite(_ss, HIGH);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PN532_SPI::writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) {
|
|
||||||
digitalWrite(_ss, LOW);
|
|
||||||
delay(2); // wake up PN532
|
|
||||||
|
|
||||||
write(DATA_WRITE);
|
|
||||||
write(PN532_PREAMBLE);
|
|
||||||
write(PN532_STARTCODE1);
|
|
||||||
write(PN532_STARTCODE2);
|
|
||||||
|
|
||||||
uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA
|
|
||||||
write(length);
|
|
||||||
write(~length + 1); // checksum of length
|
|
||||||
|
|
||||||
write(PN532_HOSTTOPN532);
|
|
||||||
uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA
|
|
||||||
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < hlen; i++) {
|
|
||||||
write(header[i]);
|
|
||||||
sum += header[i];
|
|
||||||
}
|
|
||||||
for (uint8_t i = 0; i < blen; i++) {
|
|
||||||
write(body[i]);
|
|
||||||
sum += body[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t checksum = ~sum + 1; // checksum of TFI + DATA
|
|
||||||
write(checksum);
|
|
||||||
write(PN532_POSTAMBLE);
|
|
||||||
|
|
||||||
digitalWrite(_ss, HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
int8_t PN532_SPI::readAckFrame() {
|
|
||||||
const uint8_t PN532_ACK[] = { 0, 0, 0xFF, 0, 0xFF, 0 };
|
|
||||||
|
|
||||||
uint8_t ackBuf[sizeof(PN532_ACK)];
|
|
||||||
|
|
||||||
digitalWrite(_ss, LOW);
|
|
||||||
delay(1);
|
|
||||||
write(DATA_READ);
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
|
|
||||||
ackBuf[i] = read();
|
|
||||||
}
|
|
||||||
|
|
||||||
digitalWrite(_ss, HIGH);
|
|
||||||
|
|
||||||
return memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK));
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
库代码来自:https://github.com/elechouse/PN532
|
|
||||||
删除了未使用的函数。
|
|
||||||
*/
|
|
||||||
#ifndef __PN532_SPI_H__
|
|
||||||
#define __PN532_SPI_H__
|
|
||||||
|
|
||||||
#include <SPI.h>
|
|
||||||
#include "PN532Interface.h"
|
|
||||||
class PN532_SPI : public PN532Interface {
|
|
||||||
public:
|
|
||||||
PN532_SPI(SPIClass &spi, uint8_t ss);
|
|
||||||
|
|
||||||
void begin();
|
|
||||||
void wakeup();
|
|
||||||
int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
|
|
||||||
|
|
||||||
int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout);
|
|
||||||
|
|
||||||
private:
|
|
||||||
SPIClass *_spi;
|
|
||||||
uint8_t _ss;
|
|
||||||
uint8_t command;
|
|
||||||
|
|
||||||
bool isReady();
|
|
||||||
void writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
|
|
||||||
int8_t readAckFrame();
|
|
||||||
|
|
||||||
inline void write(uint8_t data) {
|
|
||||||
_spi->transfer(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline uint8_t read() {
|
|
||||||
return _spi->transfer(0);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user