348 lines
9.4 KiB
C++
348 lines
9.4 KiB
C++
#include "uFR.h"
|
|
|
|
#define PROCESS_EXT(length) \
|
|
EXTPacket extPacket(length); \
|
|
if (extPacket.getErrorCode() != 0) return extPacket.getErrorCode()
|
|
|
|
#define PROCESS_ACK(command) \
|
|
CommonPacket ackPacket(PACKET_ACK, command); \
|
|
if (ackPacket.getErrorCode() != 0) return ackPacket.getErrorCode()
|
|
|
|
#define PROCESS_RSP(command) \
|
|
CommonPacket rspPacket(PACKET_RSP, command); \
|
|
if (rspPacket.getErrorCode() != 0) return rspPacket.getErrorCode()
|
|
|
|
#ifdef ESP32
|
|
uFR::uFR(uint8_t uart) : readerSerial(HardwareSerial(uart)) {
|
|
setPacketSerial();
|
|
}
|
|
|
|
uFR::uFR(uint8_t uart, uint8_t rx_pin, uint8_t tx_pin) : readerSerial(HardwareSerial(uart)) {
|
|
esp32_rx_pin = rx_pin;
|
|
esp32_tx_pin = tx_pin;
|
|
setPacketSerial();
|
|
}
|
|
|
|
uFR::uFR(uint8_t uart, uint8_t reset) : readerSerial(HardwareSerial(uart)) {
|
|
pinMode(reset, OUTPUT);
|
|
digitalWrite(reset, HIGH);
|
|
resetPin = reset;
|
|
setPacketSerial();
|
|
}
|
|
|
|
uFR::uFR(uint8_t uart, uint8_t reset, uint8_t rx_pin, uint8_t tx_pin) : readerSerial(HardwareSerial(uart)) {
|
|
pinMode(reset, OUTPUT);
|
|
digitalWrite(reset, HIGH);
|
|
resetPin = reset;
|
|
esp32_rx_pin = rx_pin;
|
|
esp32_tx_pin = tx_pin;
|
|
setPacketSerial();
|
|
}
|
|
|
|
#else
|
|
uFR::uFR(uint8_t rx, uint8_t tx) : readerSerial(SoftwareSerial(rx, tx)) {
|
|
setPacketSerial();
|
|
}
|
|
|
|
uFR::uFR(uint8_t rx, uint8_t tx, uint8_t reset) : readerSerial(SoftwareSerial(rx, tx)) {
|
|
pinMode(reset, OUTPUT);
|
|
digitalWrite(reset, HIGH);
|
|
resetPin = reset;
|
|
setPacketSerial();
|
|
}
|
|
#endif
|
|
|
|
void uFR::setPacketSerial() {
|
|
Packet::serial = &readerSerial;
|
|
}
|
|
|
|
void uFR::begin(unsigned long baud) {
|
|
if(resetPin != 0) {
|
|
delay(10);
|
|
digitalWrite(resetPin, LOW);
|
|
}
|
|
#ifdef ESP32
|
|
if(esp32_rx_pin != 0 && esp32_tx_pin != 0) {
|
|
readerSerial.begin(baud, SERIAL_8N1, esp32_rx_pin, esp32_tx_pin);
|
|
}
|
|
else
|
|
{
|
|
readerSerial.begin(baud);
|
|
}
|
|
#else
|
|
readerSerial.begin(baud);
|
|
#endif
|
|
|
|
}
|
|
|
|
void uFR::hardReset() {
|
|
if (resetPin != 0) {
|
|
digitalWrite(resetPin, HIGH);
|
|
delay(10);
|
|
digitalWrite(resetPin, LOW);
|
|
}
|
|
}
|
|
|
|
void uFR::flushSerial() {
|
|
while (readerSerial.available() > 0)
|
|
readerSerial.read();
|
|
}
|
|
|
|
void uFR::sendPacketCMD(uint8_t command, uint8_t EXTlength, uint8_t par0, uint8_t par1) {
|
|
uint8_t packet[PACKET_LENGTH] = {
|
|
CMD_HEADER,
|
|
command,
|
|
CMD_TRAILER,
|
|
EXTlength,
|
|
par0,
|
|
par1,
|
|
Packet::checksum(packet)
|
|
};
|
|
readerSerial.write(packet, PACKET_LENGTH);
|
|
}
|
|
|
|
void uFR::sendPacketEXT(uint8_t *packet, uint8_t length) {
|
|
readerSerial.write(packet, length);
|
|
readerSerial.write(Packet::checksum(packet, length));
|
|
}
|
|
|
|
// ========================================================================================
|
|
|
|
uint8_t uFR::setRedLED(bool state) {
|
|
flushSerial();
|
|
sendPacketCMD(RED_LIGHT_CONTROL, 0, state);
|
|
PROCESS_RSP(RED_LIGHT_CONTROL);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::setUserInterfaceSignal(uint8_t light_signal_mode, uint8_t beep_signal_mode) {
|
|
flushSerial();
|
|
sendPacketCMD(USER_INTERFACE_SIGNAL, 0, light_signal_mode, beep_signal_mode);
|
|
PROCESS_RSP(USER_INTERFACE_SIGNAL);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::setGreenLightBlinking(bool state) {
|
|
flushSerial();
|
|
sendPacketCMD(SET_LED_CONFIG, 0, state);
|
|
PROCESS_RSP(SET_LED_CONFIG);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
uint8_t uFR::getReaderType(uint8_t readerType[READER_TYPE_SIZE]) {
|
|
flushSerial();
|
|
sendPacketCMD(GET_READER_TYPE);
|
|
PROCESS_RSP(GET_READER_TYPE);
|
|
PROCESS_EXT(READER_TYPE_SIZE);
|
|
extPacket.copyDataReverse(readerType, 0, READER_TYPE_SIZE);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::getReaderSerial(uint8_t readerSerialNumber[READER_SERIAL_SIZE]) {
|
|
flushSerial();
|
|
sendPacketCMD(GET_READER_SERIAL);
|
|
PROCESS_RSP(GET_READER_SERIAL);
|
|
PROCESS_EXT(READER_SERIAL_SIZE);
|
|
extPacket.copyDataReverse(readerSerialNumber, 0, READER_SERIAL_SIZE);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::setReaderKey(uint8_t key[READER_KEY_SIZE], uint8_t index) {
|
|
flushSerial();
|
|
sendPacketCMD(READER_KEY_WRITE, READER_KEY_SIZE + 1, index);
|
|
PROCESS_ACK(READER_KEY_WRITE);
|
|
sendPacketEXT(key, READER_KEY_SIZE);
|
|
PROCESS_RSP(READER_KEY_WRITE);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::getUserData(uint8_t data[USER_DATA_SIZE]) {
|
|
flushSerial();
|
|
sendPacketCMD(USER_DATA_READ);
|
|
PROCESS_RSP(USER_DATA_READ);
|
|
PROCESS_EXT(USER_DATA_SIZE);
|
|
extPacket.copyData(data, 0, USER_DATA_SIZE);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::setUserData(uint8_t data[USER_DATA_SIZE]) {
|
|
flushSerial();
|
|
sendPacketCMD(USER_DATA_WRITE, USER_DATA_SIZE + 1);
|
|
PROCESS_ACK(USER_DATA_WRITE);
|
|
sendPacketEXT(data, USER_DATA_SIZE);
|
|
PROCESS_RSP(USER_DATA_WRITE);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::softReset() {
|
|
flushSerial();
|
|
sendPacketCMD(SELF_RESET);
|
|
PROCESS_RSP(SELF_RESET);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::getCardIDSimple(uint8_t cardID[CARD_ID_SIZE], uint8_t *cardType) {
|
|
flushSerial();
|
|
sendPacketCMD(GET_CARD_ID);
|
|
PROCESS_RSP(GET_CARD_ID);
|
|
PROCESS_EXT(CARD_ID_SIZE);
|
|
extPacket.copyDataReverse(cardID, 0, CARD_ID_SIZE);
|
|
if (cardType) *cardType = rspPacket[PAR0_BYTE];
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::getCardID(uint8_t cardID[CARD_ID_EX_SIZE], uint8_t *length, uint8_t *cardType) {
|
|
flushSerial();
|
|
sendPacketCMD(GET_CARD_ID_EX);
|
|
PROCESS_RSP(GET_CARD_ID_EX);
|
|
PROCESS_EXT(CARD_ID_EX_SIZE);
|
|
//extPacket.copyDataReverse(cardID, 0, rspPacket[PAR1_BYTE]);
|
|
//extPacket.copyData is used to make the order of bytes of cardID as on the card
|
|
extPacket.copyData(cardID, 0, rspPacket[PAR1_BYTE]);
|
|
if (cardType) *cardType = rspPacket[PAR0_BYTE];
|
|
if (length) *length = rspPacket[PAR1_BYTE];
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::getDesfireUID(uint8_t cardID[CARD_ID_EX_SIZE], uint8_t *length, uint8_t InternalAESKeyIndexReader, uint32_t AID, uint8_t key_number_in_application) {
|
|
uint8_t desfire_uid_size = 7; //as I can see in protocol, there are no length definitions. UID is always 7B.
|
|
*length = desfire_uid_size;
|
|
uint8_t data_to_send[22];
|
|
memset(data_to_send, 0, 22);
|
|
data_to_send[0]=1;
|
|
data_to_send[1]=InternalAESKeyIndexReader;
|
|
data_to_send[18] = *((uint8_t *)&AID);
|
|
data_to_send[19] = *((uint8_t *)&AID+1);
|
|
data_to_send[20] = *((uint8_t *)&AID+2);
|
|
data_to_send[21]= key_number_in_application;
|
|
|
|
/*
|
|
Serial.print("data_to_send = ");
|
|
for(int i;i<22;i++)
|
|
{
|
|
Serial.print(data_to_send[i], HEX);
|
|
Serial.print(" ");
|
|
}
|
|
Serial.print("\n");
|
|
*/
|
|
|
|
flushSerial();
|
|
sendPacketCMD(GET_DESFIRE_UID, 23);
|
|
PROCESS_ACK(GET_DESFIRE_UID);
|
|
sendPacketEXT(data_to_send, 22);
|
|
PROCESS_RSP(GET_DESFIRE_UID);
|
|
/*
|
|
Serial.print("RSP:");
|
|
for(int i;i<7;++i)
|
|
{
|
|
Serial.print(rspPacket[i], HEX);
|
|
Serial.print(" ");
|
|
}
|
|
Serial.print("\n");
|
|
|
|
*/
|
|
if(rspPacket[3]!=12)
|
|
{
|
|
return PARAMETERS_ERROR;
|
|
}
|
|
PROCESS_EXT(11);
|
|
extPacket.copyData(cardID, 0, desfire_uid_size);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::getDesfireUIDPK(uint8_t cardID[CARD_ID_EX_SIZE], uint8_t *length, uint8_t *AESKey, uint32_t AID, uint8_t key_number_in_application) {
|
|
uint8_t desfire_uid_size = 7; //as I can see in protocol, there are no length definitions. UID is always 7B.
|
|
*length = desfire_uid_size;
|
|
uint8_t data_to_send[22];
|
|
memset(data_to_send, 0, 22);
|
|
data_to_send[0]=0;
|
|
data_to_send[1]=0;
|
|
memcpy(&data_to_send[2], AESKey, 16);
|
|
data_to_send[18] = *((uint8_t *)&AID);
|
|
data_to_send[19] = *((uint8_t *)&AID+1);
|
|
data_to_send[20] = *((uint8_t *)&AID+2);
|
|
data_to_send[21]= key_number_in_application;
|
|
|
|
/*
|
|
Serial.print("data_to_send = ");
|
|
for(int i;i<22;i++)
|
|
{
|
|
Serial.print(data_to_send[i], HEX);
|
|
Serial.print(" ");
|
|
}
|
|
Serial.print("\n");
|
|
*/
|
|
|
|
flushSerial();
|
|
sendPacketCMD(GET_DESFIRE_UID, 23);
|
|
PROCESS_ACK(GET_DESFIRE_UID);
|
|
sendPacketEXT(data_to_send, 22);
|
|
PROCESS_RSP(GET_DESFIRE_UID);
|
|
/*
|
|
Serial.print("RSP:");
|
|
for(int i;i<7;++i)
|
|
{
|
|
Serial.print(rspPacket[i], HEX);
|
|
Serial.print(" ");
|
|
}
|
|
Serial.print("\n");
|
|
|
|
*/
|
|
if(rspPacket[3]!=12)
|
|
{
|
|
return PARAMETERS_ERROR;
|
|
}
|
|
PROCESS_EXT(11);
|
|
extPacket.copyData(cardID, 0, desfire_uid_size);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t uFR::getCardTypeDLogic(uint8_t *cardType) {
|
|
flushSerial();
|
|
sendPacketCMD(GET_DLOGIC_CARD_TYPE);
|
|
PROCESS_RSP(GET_DLOGIC_CARD_TYPE);
|
|
*cardType = rspPacket[PAR0_BYTE];
|
|
return 0;
|
|
}
|
|
|
|
// ========================================================================================
|
|
|
|
// Needs beautifying
|
|
const char * TypeDLogicToString(uint8_t type) {
|
|
switch (type) {
|
|
case 0x00: return "TAG_UNKNOWN"; break;
|
|
case 0x01: return "DL_MIFARE_ULTRALIGHT"; break;
|
|
case 0x02: return "DL_MIFARE_ULTRALIGHT_EV1_11"; break;
|
|
case 0x03: return "DL_MIFARE_ULTRALIGHT_EV1_21"; break;
|
|
case 0x04: return "DL_MIFARE_ULTRALIGHT_C"; break;
|
|
case 0x05: return "DL_NTAG_203"; break;
|
|
case 0x06: return "DL_NTAG_210"; break;
|
|
case 0x07: return "DL_NTAG_212"; break;
|
|
case 0x08: return "DL_NTAG_213"; break;
|
|
case 0x09: return "DL_NTAG_215"; break;
|
|
case 0x0A: return "DL_NTAG_216"; break;
|
|
case 0x0B: return "DL_MIKRON_MIK640D"; break;
|
|
case 0x0C: return "NFC_T2T_GENERIC"; break;
|
|
case 0x20: return "DL_MIFARE_MINI"; break;
|
|
case 0x21: return "DL_MIFARE_CLASSIC_1K"; break;
|
|
case 0x22: return "DL_MIFARE_CLASSIC_4K"; break;
|
|
case 0x23: return "DL_MIFARE_PLUS_S_2K"; break;
|
|
case 0x24: return "DL_MIFARE_PLUS_S_4K"; break;
|
|
case 0x25: return "DL_MIFARE_PLUS_X_2K"; break;
|
|
case 0x26: return "DL_MIFARE_PLUS_X_4K"; break;
|
|
case 0x27: return "DL_MIFARE_DESFIRE"; break;
|
|
case 0x28: return "DL_MIFARE_DESFIRE_EV1_2K"; break;
|
|
case 0x29: return "DL_MIFARE_DESFIRE_EV1_4K"; break;
|
|
case 0x2A: return "DL_MIFARE_DESFIRE_EV1_8K"; break;
|
|
case 0x2B: return "DL_MIFARE_DESFIRE_EV2_2K"; break;
|
|
case 0x2C: return "DL_MIFARE_DESFIRE_EV2_4K"; break;
|
|
case 0x2D: return "DL_MIFARE_DESFIRE_EV2_8K"; break;
|
|
case 0x40: return "DL_GENERIC_ISO14443_4"; break;
|
|
case 0x41: return "DL_GENERIC_ISO14443_TYPE_B"; break;
|
|
case 0x80: return "DL_IMEI_UID"; break;
|
|
default: return "TYPE_ERROR";
|
|
}
|
|
}
|