mirror of
https://github.com/brmlab/brmdoor.git
synced 2025-06-07 11:14:01 +02:00
commit
066dcc686a
15 changed files with 2211 additions and 69 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
.*.swp
|
||||
session
|
||||
tags
|
43
README
43
README
|
@ -1,8 +1,49 @@
|
|||
=== Brmdoor control software ===
|
||||
|
||||
brmd/ - integration hub that collects data from various sources and provides unified reporting on IRC and web etc.
|
||||
brmd/ - integration hub that collects data from various sources and provides
|
||||
unified reporting on IRC and web etc.
|
||||
|
||||
brmdoor/ - Arduino software
|
||||
|
||||
|
||||
Project webpage: http://brmlab.cz/project/brmdoor
|
||||
|
||||
Note for PN532 version: if you want brmdoor to add card UID after "CARD"
|
||||
message (not just nick), set printFullUID to true in brmdoor/brmdoor.ino.
|
||||
|
||||
|
||||
==== Adding new UIDs to the database ====
|
||||
|
||||
There are two lists - the new proper and the old deperecated with truncated UIDs.
|
||||
When adding, the new list is better place.
|
||||
|
||||
The new proper list is searched for UIDs first.
|
||||
|
||||
===== Using the new proper list - recommended =====
|
||||
|
||||
Edit the cardids_proper.h file and add your UID and nick to a new line, which
|
||||
will become part of the ACLproper array. E.g. to add UID 04c24ce9ad2780 that is
|
||||
7 bytes long and adding nick "voyeur1", add line:
|
||||
|
||||
{ 7, {0x04, 0xc2 0x4c, 0xe9, 0xad, 0x27, 0x80}, "voyeur1" },
|
||||
|
||||
|
||||
===== Using the old broken truncated list - not recommended =====
|
||||
|
||||
Edit the cardids.h file. If the new card UID is 4 bytes long, e.g. 35b018d4,
|
||||
compute BCC, which is xor of these four bytes (0x49 in this case). Then add
|
||||
|
||||
{ {0x00, 0x00, 0x35, 0xb0, 0x18, 0xd4, 0x49}, "mifare_classic_1" },
|
||||
|
||||
The first two bytes are magic bytes that originate in the old reader, just use
|
||||
two zero bytes as above. The last byte is BCC we computed before. But you can
|
||||
use zero, the software doesn't need it.
|
||||
|
||||
If the card UID is longer than 4 bytes (7 or 10 bytes), e.g. 04c24ce9ad2780,
|
||||
discard last four bytes of the UID and prepend 0x88. Use this "newly" created
|
||||
UID as if the card had only 4 byte UID, just like above.
|
||||
|
||||
{ {0x00, 0x00, 0x88, 0x04, 0xc2, 0x4c, 0x02}, "truncated_voyeur1" },
|
||||
|
||||
The old reader didn't support ISO14443 SELECT cascade 2 and 3. Hence the broken
|
||||
UIDs.
|
||||
|
|
|
@ -11,7 +11,7 @@ use Image::Magick;
|
|||
|
||||
our @channels = ("#brmlab", "#brmstatus");
|
||||
our $streamurl = "http://brmlab.cz/stream";
|
||||
our $devdoor = $ARGV[0]; $devdoor ||= "/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A700e1qB-if00-port0";
|
||||
our $devdoor = $ARGV[0]; $devdoor ||= "/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A70078Q1-if00-port0";
|
||||
our $devasign = $ARGV[1]; $devasign ||= "/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0";
|
||||
our ($status, $streaming, $dooropen, $topic) = (0, 0, 0, 'BRMLAB OPEN');
|
||||
our ($laststchange, $lastunlock) = (time, 0);
|
||||
|
|
1
brmdoor/.gitignore
vendored
1
brmdoor/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
cardids.h
|
||||
cardids_proper.h
|
||||
|
|
1036
brmdoor/AdafruitPN532/Adafruit_PN532.cpp
Normal file
1036
brmdoor/AdafruitPN532/Adafruit_PN532.cpp
Normal file
File diff suppressed because it is too large
Load diff
184
brmdoor/AdafruitPN532/Adafruit_PN532.h
Normal file
184
brmdoor/AdafruitPN532/Adafruit_PN532.h
Normal file
|
@ -0,0 +1,184 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file Adafruit_PN532.h
|
||||
@author Adafruit Industries
|
||||
@license BSD (see license.txt)
|
||||
|
||||
|
||||
This is a library for the Adafruit PN532 NFC/RFID breakout boards
|
||||
This library works with the Adafruit NFC breakout
|
||||
----> https://www.adafruit.com/products/364
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use SPI to communicate, 4 required to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
@section HISTORY
|
||||
|
||||
v1.1 - Added full command list
|
||||
- Added 'verbose' mode flag to constructor to toggle debug output
|
||||
- Changed readPassiveTargetID() to return variable length values
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#define PN532_PREAMBLE (0x00)
|
||||
#define PN532_STARTCODE1 (0x00)
|
||||
#define PN532_STARTCODE2 (0xFF)
|
||||
#define PN532_POSTAMBLE (0x00)
|
||||
|
||||
#define PN532_HOSTTOPN532 (0xD4)
|
||||
|
||||
// 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_WAKEUP (0x55)
|
||||
|
||||
#define PN532_SPI_STATREAD (0x02)
|
||||
#define PN532_SPI_DATAWRITE (0x01)
|
||||
#define PN532_SPI_DATAREAD (0x03)
|
||||
#define PN532_SPI_READY (0x01)
|
||||
|
||||
#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_TRANSFER (0xB0)
|
||||
#define MIFARE_CMD_DECREMENT (0xC0)
|
||||
#define MIFARE_CMD_INCREMENT (0xC1)
|
||||
#define MIFARE_CMD_STORE (0xC2)
|
||||
|
||||
// Prefixes for NDEF Records (to identify record type)
|
||||
#define NDEF_URIPREFIX_NONE (0x00)
|
||||
#define NDEF_URIPREFIX_HTTP_WWWDOT (0x01)
|
||||
#define NDEF_URIPREFIX_HTTPS_WWWDOT (0x02)
|
||||
#define NDEF_URIPREFIX_HTTP (0x03)
|
||||
#define NDEF_URIPREFIX_HTTPS (0x04)
|
||||
#define NDEF_URIPREFIX_TEL (0x05)
|
||||
#define NDEF_URIPREFIX_MAILTO (0x06)
|
||||
#define NDEF_URIPREFIX_FTP_ANONAT (0x07)
|
||||
#define NDEF_URIPREFIX_FTP_FTPDOT (0x08)
|
||||
#define NDEF_URIPREFIX_FTPS (0x09)
|
||||
#define NDEF_URIPREFIX_SFTP (0x0A)
|
||||
#define NDEF_URIPREFIX_SMB (0x0B)
|
||||
#define NDEF_URIPREFIX_NFS (0x0C)
|
||||
#define NDEF_URIPREFIX_FTP (0x0D)
|
||||
#define NDEF_URIPREFIX_DAV (0x0E)
|
||||
#define NDEF_URIPREFIX_NEWS (0x0F)
|
||||
#define NDEF_URIPREFIX_TELNET (0x10)
|
||||
#define NDEF_URIPREFIX_IMAP (0x11)
|
||||
#define NDEF_URIPREFIX_RTSP (0x12)
|
||||
#define NDEF_URIPREFIX_URN (0x13)
|
||||
#define NDEF_URIPREFIX_POP (0x14)
|
||||
#define NDEF_URIPREFIX_SIP (0x15)
|
||||
#define NDEF_URIPREFIX_SIPS (0x16)
|
||||
#define NDEF_URIPREFIX_TFTP (0x17)
|
||||
#define NDEF_URIPREFIX_BTSPP (0x18)
|
||||
#define NDEF_URIPREFIX_BTL2CAP (0x19)
|
||||
#define NDEF_URIPREFIX_BTGOEP (0x1A)
|
||||
#define NDEF_URIPREFIX_TCPOBEX (0x1B)
|
||||
#define NDEF_URIPREFIX_IRDAOBEX (0x1C)
|
||||
#define NDEF_URIPREFIX_FILE (0x1D)
|
||||
#define NDEF_URIPREFIX_URN_EPC_ID (0x1E)
|
||||
#define NDEF_URIPREFIX_URN_EPC_TAG (0x1F)
|
||||
#define NDEF_URIPREFIX_URN_EPC_PAT (0x20)
|
||||
#define NDEF_URIPREFIX_URN_EPC_RAW (0x21)
|
||||
#define NDEF_URIPREFIX_URN_EPC (0x22)
|
||||
#define NDEF_URIPREFIX_URN_NFC (0x23)
|
||||
|
||||
#define PN532_GPIO_VALIDATIONBIT (0x80)
|
||||
#define PN532_GPIO_P30 (0)
|
||||
#define PN532_GPIO_P31 (1)
|
||||
#define PN532_GPIO_P32 (2)
|
||||
#define PN532_GPIO_P33 (3)
|
||||
#define PN532_GPIO_P34 (4)
|
||||
#define PN532_GPIO_P35 (5)
|
||||
|
||||
class Adafruit_PN532{
|
||||
public:
|
||||
Adafruit_PN532(uint8_t cs, uint8_t clk, uint8_t mosi, uint8_t miso);
|
||||
void begin(void);
|
||||
|
||||
// Generic PN532 functions
|
||||
boolean SAMConfig(void);
|
||||
uint32_t getFirmwareVersion(void);
|
||||
boolean sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout = 1000);
|
||||
boolean writeGPIO(uint8_t pinstate);
|
||||
uint8_t readGPIO(void);
|
||||
boolean setPassiveActivationRetries(uint8_t maxRetries);
|
||||
|
||||
// ISO14443A functions
|
||||
boolean readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength);
|
||||
|
||||
// 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);
|
||||
uint8_t mifareclassic_FormatNDEF (void);
|
||||
uint8_t mifareclassic_WriteNDEFURI (uint8_t sectorNumber, uint8_t uriIdentifier, const char * url);
|
||||
|
||||
// Mifare Ultralight functions
|
||||
uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t * buffer);
|
||||
|
||||
// Help functions to display formatted text
|
||||
static void PrintHex(const byte * data, const uint32_t numBytes);
|
||||
static void PrintHexChar(const byte * pbtData, const uint32_t numBytes);
|
||||
|
||||
private:
|
||||
uint8_t _ss, _clk, _mosi, _miso;
|
||||
uint8_t _uid[7]; // ISO14443A uid
|
||||
uint8_t _uidLen; // uid len
|
||||
uint8_t _key[6]; // Mifare Classic key
|
||||
|
||||
boolean spi_readack();
|
||||
uint8_t readspistatus(void);
|
||||
void readspidata(uint8_t* buff, uint8_t n);
|
||||
void spiwritecommand(uint8_t* cmd, uint8_t cmdlen);
|
||||
void spiwrite(uint8_t c);
|
||||
uint8_t spiread(void);
|
||||
};
|
|
@ -0,0 +1,83 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file iso14443a_uid.pde
|
||||
@author Adafruit Industries
|
||||
@license BSD (see license.txt)
|
||||
|
||||
This example will attempt to connect to an ISO14443A
|
||||
card or tag and retrieve some basic information about it
|
||||
that can be used to determine what type of card it is.
|
||||
|
||||
Note that you need the baud rate to be 115200 because we need to print
|
||||
out the data and read from the card at the same time!
|
||||
|
||||
This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards
|
||||
This library works with the Adafruit NFC breakout
|
||||
----> https://www.adafruit.com/products/364
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use SPI to communicate, 4 required to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#include <Adafruit_PN532.h>
|
||||
|
||||
#define SCK (2)
|
||||
#define MOSI (3)
|
||||
#define SS (4)
|
||||
#define MISO (5)
|
||||
|
||||
Adafruit_PN532 nfc(SCK, MISO, MOSI, SS);
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Hello!");
|
||||
|
||||
nfc.begin();
|
||||
|
||||
uint32_t versiondata = nfc.getFirmwareVersion();
|
||||
if (! versiondata) {
|
||||
Serial.print("Didn't find PN53x board");
|
||||
while (1); // halt
|
||||
}
|
||||
|
||||
// Got ok data, print it out!
|
||||
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
|
||||
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
|
||||
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
|
||||
|
||||
// configure board to read RFID tags
|
||||
nfc.SAMConfig();
|
||||
|
||||
Serial.println("Waiting for an ISO14443A card");
|
||||
}
|
||||
|
||||
|
||||
void loop(void) {
|
||||
boolean success;
|
||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
|
||||
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
|
||||
|
||||
// Wait for an ISO14443A type cards (Mifare, etc.). When one is found
|
||||
// 'uid' will be populated with the UID, and uidLength will indicate
|
||||
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
|
||||
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
|
||||
|
||||
if (success) {
|
||||
Serial.println("Found a card!");
|
||||
Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
|
||||
Serial.print("UID Value: ");
|
||||
for (uint8_t i=0; i < uidLength; i++)
|
||||
{
|
||||
Serial.print(" 0x");Serial.print(uid[i], HEX);
|
||||
}
|
||||
Serial.println("");
|
||||
// Wait 1 second before continuing
|
||||
delay(1000);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file mifareclassic_formatndef.pde
|
||||
@author Adafruit Industries
|
||||
@license BSD (see license.txt)
|
||||
|
||||
This example attempts to format a Mifare Classic
|
||||
card for NDEF Records and writes an NDEF URI Record
|
||||
|
||||
Note that you need the baud rate to be 115200 because we need to print
|
||||
out the data and read from the card at the same time!
|
||||
|
||||
This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards
|
||||
This library works with the Adafruit NFC breakout
|
||||
----> https://www.adafruit.com/products/364
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use SPI to communicate, 4 required to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#include <Adafruit_PN532.h>
|
||||
|
||||
#define SCK (2)
|
||||
#define MOSI (3)
|
||||
#define SS (4)
|
||||
#define MISO (5)
|
||||
|
||||
Adafruit_PN532 nfc(SCK, MISO, MOSI, SS);
|
||||
|
||||
const char * url = "adafruit.com";
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Looking for PN532...");
|
||||
|
||||
nfc.begin();
|
||||
|
||||
uint32_t versiondata = nfc.getFirmwareVersion();
|
||||
if (! versiondata) {
|
||||
Serial.print("Didn't find PN53x board");
|
||||
while (1); // halt
|
||||
}
|
||||
|
||||
// Got ok data, print it out!
|
||||
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
|
||||
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
|
||||
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
|
||||
|
||||
// configure board to read RFID tags
|
||||
nfc.SAMConfig();
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("PLEASE NOTE: Formatting your card for NDEF records will change the");
|
||||
Serial.println("authentication keys and you will no longer be able to read the");
|
||||
Serial.println("card as a normal Mifare card without resetting all keys. Try to keep");
|
||||
Serial.println("seperate cards for NDEF and non-NDEF purposes.");
|
||||
Serial.println("");
|
||||
Serial.println("Place your Mifare Classic card on the reader to format with NDEF");
|
||||
Serial.println("and press any key to continue ...");
|
||||
// Wait for user input before proceeding
|
||||
Serial.flush();
|
||||
while (!Serial.available());
|
||||
Serial.flush();
|
||||
}
|
||||
|
||||
void loop(void) {
|
||||
uint8_t success; // Flag to check if there was an error with the PN532
|
||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
|
||||
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
|
||||
bool authenticated = false; // Flag to indicate if the sector is authenticated
|
||||
|
||||
// Use the default key
|
||||
uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
// Wait for an ISO14443A type card (Mifare, etc.). When one is found
|
||||
// 'uid' will be populated with the UID, and uidLength will indicate
|
||||
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
|
||||
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
|
||||
|
||||
if (success)
|
||||
{
|
||||
// Display some basic information about the card
|
||||
Serial.println("Found an ISO14443A card");
|
||||
Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
|
||||
Serial.print(" UID Value: ");
|
||||
nfc.PrintHex(uid, uidLength);
|
||||
Serial.println("");
|
||||
|
||||
// Make sure this is a Mifare Classic card
|
||||
if (uidLength != 4)
|
||||
{
|
||||
Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!");
|
||||
return;
|
||||
}
|
||||
|
||||
// We probably have a Mifare Classic card ...
|
||||
Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
|
||||
|
||||
// Try to format the card for NDEF data
|
||||
success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 0, 0, keya);
|
||||
if (!success)
|
||||
{
|
||||
Serial.println("Unable to authenticate block 0 to enable card formatting!");
|
||||
return;
|
||||
}
|
||||
success = nfc.mifareclassic_FormatNDEF();
|
||||
if (!success)
|
||||
{
|
||||
Serial.println("Unable to format the card for NDEF");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("Card has been formatted for NDEF data using MAD1");
|
||||
|
||||
// Try to authenticate block 4 (first block of sector 1) using our key
|
||||
success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keya);
|
||||
|
||||
// Make sure the authentification process didn't fail
|
||||
if (!success)
|
||||
{
|
||||
Serial.println("Authentication failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to write a URL
|
||||
Serial.println("Writing URI to sector 1 as an NDEF Message");
|
||||
|
||||
// Authenticated seems to have worked
|
||||
// Try to write an NDEF record to sector 1
|
||||
// Use 0x01 for the URI Identifier Code to prepend "http://www."
|
||||
// to the url (and save some space). For information on URI ID Codes
|
||||
// see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef
|
||||
if (strlen(url) > 38)
|
||||
{
|
||||
// The length is also checked in the WriteNDEFURI function, but lets
|
||||
// warn users here just in case they change the value and it's bigger
|
||||
// than it should be
|
||||
Serial.println("URI is too long ... must be less than 38 characters long");
|
||||
return;
|
||||
}
|
||||
|
||||
// URI is within size limits ... write it to the card and report success/failure
|
||||
success = nfc.mifareclassic_WriteNDEFURI(1, NDEF_URIPREFIX_HTTP_WWWDOT, url);
|
||||
if (success)
|
||||
{
|
||||
Serial.println("NDEF URI Record written to sector 1");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("NDEF Record creation failed! :(");
|
||||
}
|
||||
}
|
||||
|
||||
// Wait a bit before trying again
|
||||
Serial.println("\n\nDone!");
|
||||
Serial.flush();
|
||||
while (!Serial.available());
|
||||
Serial.flush();
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file mifareclassic_memdump.pde
|
||||
@author Adafruit Industries
|
||||
@license BSD (see license.txt)
|
||||
|
||||
This example attempts to dump the contents of a Mifare Classic 1K card
|
||||
|
||||
Note that you need the baud rate to be 115200 because we need to print
|
||||
out the data and read from the card at the same time!
|
||||
|
||||
This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards
|
||||
This library works with the Adafruit NFC breakout
|
||||
----> https://www.adafruit.com/products/364
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use SPI to communicate, 4 required to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#include <Adafruit_PN532.h>
|
||||
|
||||
#define SCK (2)
|
||||
#define MOSI (3)
|
||||
#define SS (4)
|
||||
#define MISO (5)
|
||||
|
||||
Adafruit_PN532 nfc(SCK, MISO, MOSI, SS);
|
||||
|
||||
void setup(void) {
|
||||
// has to be fast to dump the entire memory contents!
|
||||
Serial.begin(115200);
|
||||
Serial.println("Looking for PN532...");
|
||||
|
||||
nfc.begin();
|
||||
|
||||
uint32_t versiondata = nfc.getFirmwareVersion();
|
||||
if (! versiondata) {
|
||||
Serial.print("Didn't find PN53x board");
|
||||
while (1); // halt
|
||||
}
|
||||
// Got ok data, print it out!
|
||||
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
|
||||
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
|
||||
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
|
||||
|
||||
// configure board to read RFID tags
|
||||
nfc.SAMConfig();
|
||||
|
||||
Serial.println("Waiting for an ISO14443A Card ...");
|
||||
}
|
||||
|
||||
|
||||
void loop(void) {
|
||||
uint8_t success; // Flag to check if there was an error with the PN532
|
||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
|
||||
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
|
||||
uint8_t currentblock; // Counter to keep track of which block we're on
|
||||
bool authenticated = false; // Flag to indicate if the sector is authenticated
|
||||
uint8_t data[16]; // Array to store block data during reads
|
||||
|
||||
// Use the default KEYA: FF FF FF FF FF FF
|
||||
uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
uint8_t keyb[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
// uint8_t keya[6] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 };
|
||||
// uint8_t keyb[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 };
|
||||
|
||||
// Wait for an ISO14443A type cards (Mifare, etc.). When one is found
|
||||
// 'uid' will be populated with the UID, and uidLength will indicate
|
||||
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
|
||||
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
|
||||
|
||||
if (success) {
|
||||
// Display some basic information about the card
|
||||
Serial.println("Found an ISO14443A card");
|
||||
Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
|
||||
Serial.print(" UID Value: ");
|
||||
nfc.PrintHex(uid, uidLength);
|
||||
Serial.println("");
|
||||
|
||||
if (uidLength == 4)
|
||||
{
|
||||
// We probably have a Mifare Classic card ...
|
||||
Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
|
||||
|
||||
// Now we try to go through all 16 sector (each having 4 blocks)
|
||||
// authenticating each sector, and then dumping the blocks
|
||||
for (currentblock = 0; currentblock < 64; currentblock++)
|
||||
{
|
||||
// Check if this is a new block so that we can reauthenticate
|
||||
if (nfc.mifareclassic_IsFirstBlock(currentblock)) authenticated = false;
|
||||
|
||||
// If the sector hasn't been authenticated, do so first
|
||||
if (!authenticated)
|
||||
{
|
||||
// Starting of a new sector ... try to to authenticate
|
||||
Serial.print("------------------------Sector ");Serial.print(currentblock/4, DEC);Serial.println("-------------------------");
|
||||
if (currentblock == 0)
|
||||
{
|
||||
success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 0, keya);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 0, keyb);
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
authenticated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Authentication error");
|
||||
}
|
||||
}
|
||||
// If we're still not authenticated just skip the block
|
||||
if (!authenticated)
|
||||
{
|
||||
Serial.print("Block ");Serial.print(currentblock, DEC);Serial.println(" unable to authenticate");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Authenticated ... we should be able to read the block now
|
||||
// Dump the data into the 'data' array
|
||||
success = nfc.mifareclassic_ReadDataBlock(currentblock, data);
|
||||
if (success)
|
||||
{
|
||||
// Read successful
|
||||
Serial.print("Block ");Serial.print(currentblock, DEC);
|
||||
if (currentblock < 10)
|
||||
{
|
||||
Serial.print(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(" ");
|
||||
}
|
||||
// Dump the raw data
|
||||
nfc.PrintHexChar(data, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Oops ... something happened
|
||||
Serial.print("Block ");Serial.print(currentblock, DEC);
|
||||
Serial.println(" unable to read this block");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!");
|
||||
}
|
||||
}
|
||||
// Wait a bit before trying again
|
||||
Serial.println("\n\nSend a character to run the mem dumper again!");
|
||||
Serial.flush();
|
||||
while (!Serial.available());
|
||||
Serial.flush();
|
||||
}
|
||||
|
162
brmdoor/AdafruitPN532/examples/readMifare/readMifare.pde
Normal file
162
brmdoor/AdafruitPN532/examples/readMifare/readMifare.pde
Normal file
|
@ -0,0 +1,162 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file readMifare.pde
|
||||
@author Adafruit Industries
|
||||
@license BSD (see license.txt)
|
||||
|
||||
This example will wait for any ISO14443A card or tag, and
|
||||
depending on the size of the UID will attempt to read from it.
|
||||
|
||||
If the card has a 4-byte UID it is probably a Mifare
|
||||
Classic card, and the following steps are taken:
|
||||
|
||||
- Authenticate block 4 (the first block of Sector 1) using
|
||||
the default KEYA of 0XFF 0XFF 0XFF 0XFF 0XFF 0XFF
|
||||
- If authentication succeeds, we can then read any of the
|
||||
4 blocks in that sector (though only block 4 is read here)
|
||||
|
||||
If the card has a 7-byte UID it is probably a Mifare
|
||||
Ultralight card, and the 4 byte pages can be read directly.
|
||||
Page 4 is read by default since this is the first 'general-
|
||||
purpose' page on the tags.
|
||||
|
||||
|
||||
This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards
|
||||
This library works with the Adafruit NFC breakout
|
||||
----> https://www.adafruit.com/products/364
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use SPI to communicate, 4 required to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#include <Adafruit_PN532.h>
|
||||
|
||||
#define SCK (2)
|
||||
#define MOSI (3)
|
||||
#define SS (4)
|
||||
#define MISO (5)
|
||||
|
||||
Adafruit_PN532 nfc(SCK, MISO, MOSI, SS);
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(9600);
|
||||
Serial.println("Hello!");
|
||||
|
||||
nfc.begin();
|
||||
|
||||
uint32_t versiondata = nfc.getFirmwareVersion();
|
||||
if (! versiondata) {
|
||||
Serial.print("Didn't find PN53x board");
|
||||
while (1); // halt
|
||||
}
|
||||
// Got ok data, print it out!
|
||||
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
|
||||
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
|
||||
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
|
||||
|
||||
// configure board to read RFID tags
|
||||
nfc.SAMConfig();
|
||||
|
||||
Serial.println("Waiting for an ISO14443A Card ...");
|
||||
}
|
||||
|
||||
|
||||
void loop(void) {
|
||||
uint8_t success;
|
||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
|
||||
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
|
||||
|
||||
// Wait for an ISO14443A type cards (Mifare, etc.). When one is found
|
||||
// 'uid' will be populated with the UID, and uidLength will indicate
|
||||
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
|
||||
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
|
||||
|
||||
if (success) {
|
||||
// Display some basic information about the card
|
||||
Serial.println("Found an ISO14443A card");
|
||||
Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
|
||||
Serial.print(" UID Value: ");
|
||||
nfc.PrintHex(uid, uidLength);
|
||||
Serial.println("");
|
||||
|
||||
if (uidLength == 4)
|
||||
{
|
||||
// We probably have a Mifare Classic card ...
|
||||
Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
|
||||
|
||||
// Now we need to try to authenticate it for read/write access
|
||||
// Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
|
||||
Serial.println("Trying to authenticate block 4 with default KEYA value");
|
||||
uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
// Start with block 4 (the first block of sector 1) since sector 0
|
||||
// contains the manufacturer data and it's probably better just
|
||||
// to leave it alone unless you know what you're doing
|
||||
success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);
|
||||
|
||||
if (success)
|
||||
{
|
||||
Serial.println("Sector 1 (Blocks 4..7) has been authenticated");
|
||||
uint8_t data[16];
|
||||
|
||||
// If you want to write something to block 4 to test with, uncomment
|
||||
// the following line and this text should be read back in a minute
|
||||
// data = { 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0};
|
||||
// success = nfc.mifareclassic_WriteDataBlock (4, data);
|
||||
|
||||
// Try to read the contents of block 4
|
||||
success = nfc.mifareclassic_ReadDataBlock(4, data);
|
||||
|
||||
if (success)
|
||||
{
|
||||
// Data seems to have been read ... spit it out
|
||||
Serial.println("Reading Block 4:");
|
||||
nfc.PrintHexChar(data, 16);
|
||||
Serial.println("");
|
||||
|
||||
// Wait a bit before reading the card again
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Ooops ... unable to read the requested block. Try another key?");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Ooops ... authentication failed: Try another key?");
|
||||
}
|
||||
}
|
||||
|
||||
if (uidLength == 7)
|
||||
{
|
||||
// We probably have a Mifare Ultralight card ...
|
||||
Serial.println("Seems to be a Mifare Ultralight tag (7 byte UID)");
|
||||
|
||||
// Try to read the first general-purpose user page (#4)
|
||||
Serial.println("Reading page 4");
|
||||
uint8_t data[32];
|
||||
success = nfc.mifareultralight_ReadPage (4, data);
|
||||
if (success)
|
||||
{
|
||||
// Data seems to have been read ... spit it out
|
||||
nfc.PrintHexChar(data, 4);
|
||||
Serial.println("");
|
||||
|
||||
// Wait a bit before reading the card again
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Ooops ... unable to read the requested page!?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file readMifareClassic.pde
|
||||
@author Adafruit Industries
|
||||
@license BSD (see license.txt)
|
||||
|
||||
This example will wait for any ISO14443A card or tag, and
|
||||
depending on the size of the UID will attempt to read from it.
|
||||
|
||||
If the card has a 4-byte UID it is probably a Mifare
|
||||
Classic card, and the following steps are taken:
|
||||
|
||||
Reads the 4 byte (32 bit) ID of a MiFare Classic card.
|
||||
Since the classic cards have only 32 bit identifiers you can stick
|
||||
them in a single variable and use that to compare card ID's as a
|
||||
number. This doesn't work for ultralight cards that have longer 7
|
||||
byte IDs!
|
||||
|
||||
Note that you need the baud rate to be 115200 because we need to
|
||||
print out the data and read from the card at the same time!
|
||||
|
||||
This is an example sketch for the Adafruit PN532 NFC/RFID breakout boards
|
||||
This library works with the Adafruit NFC breakout
|
||||
----> https://www.adafruit.com/products/364
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use SPI to communicate, 4 required to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#include <Adafruit_PN532.h>
|
||||
|
||||
#define SCK (2)
|
||||
#define MOSI (3)
|
||||
#define SS (4)
|
||||
#define MISO (5)
|
||||
|
||||
Adafruit_PN532 nfc(SCK, MISO, MOSI, SS);
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Hello!");
|
||||
|
||||
nfc.begin();
|
||||
|
||||
uint32_t versiondata = nfc.getFirmwareVersion();
|
||||
if (! versiondata) {
|
||||
Serial.print("Didn't find PN53x board");
|
||||
while (1); // halt
|
||||
}
|
||||
// Got ok data, print it out!
|
||||
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
|
||||
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
|
||||
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
|
||||
|
||||
// configure board to read RFID tags
|
||||
nfc.SAMConfig();
|
||||
|
||||
Serial.println("Waiting for an ISO14443A Card ...");
|
||||
}
|
||||
|
||||
|
||||
void loop(void) {
|
||||
uint8_t success;
|
||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
|
||||
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
|
||||
|
||||
// Wait for an ISO14443A type cards (Mifare, etc.). When one is found
|
||||
// 'uid' will be populated with the UID, and uidLength will indicate
|
||||
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
|
||||
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
|
||||
|
||||
if (success) {
|
||||
// Display some basic information about the card
|
||||
Serial.println("Found an ISO14443A card");
|
||||
Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
|
||||
Serial.print(" UID Value: ");
|
||||
nfc.PrintHex(uid, uidLength);
|
||||
|
||||
if (uidLength == 4)
|
||||
{
|
||||
// We probably have a Mifare Classic card ...
|
||||
uint32_t cardid = uid[0];
|
||||
cardid <<= 8;
|
||||
cardid |= uid[1];
|
||||
cardid <<= 8;
|
||||
cardid |= uid[2];
|
||||
cardid <<= 8;
|
||||
cardid |= uid[3];
|
||||
Serial.print("Seems to be a Mifare Classic card #");
|
||||
Serial.println(cardid);
|
||||
}
|
||||
Serial.println("");
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,6 @@ ARDUINO_PORT = /dev/ttyUSB0
|
|||
|
||||
TARGET = brmdoor
|
||||
|
||||
ARDUINO_LIBS = SoftwareSerial
|
||||
ARDUINO_LIBS = SoftwareSerial AdafruitPN532
|
||||
|
||||
include /usr/share/arduino/Arduino.mk
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#define MUSIC 1
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
#include <Adafruit_PN532.h>
|
||||
|
||||
// pins
|
||||
const int magnetPin = 10;
|
||||
const int soundPin = 9; /* piezo in series with 100R */
|
||||
|
@ -14,24 +16,101 @@ const int doorLock = 4;
|
|||
const int rfidRx = 3;
|
||||
const int rfidTx = 2;
|
||||
|
||||
// Pins where Adafruit PN532 shield is connected.
|
||||
// Note that these are the analog pins used in digital mode - no other pins
|
||||
// were available.
|
||||
const int PN532_SCK = A3;
|
||||
const int PN532_MOSI = A2;
|
||||
const int PN532_SS = A1;
|
||||
const int PN532_MISO = A0;
|
||||
|
||||
// Set to true if you want to have correct UID printed in hex after CARD
|
||||
// message into UART (case when card is known).
|
||||
bool printFullUID = true;
|
||||
|
||||
// If set to true, will add string "proper" after the CARD message to signify
|
||||
// that the UID was found in the proper ACL list.
|
||||
bool printProper = true;
|
||||
|
||||
// Max retries to read card before timeout, 200 is around 1 second, 0xFF means
|
||||
// wait forever (constitutes blocking read).
|
||||
uint8_t pn532MaxRetries = 200;
|
||||
bool pn532Working; //whether we have connected and working chip
|
||||
|
||||
int statusState = 0, statusStateOverride = 0;
|
||||
int videoState = 0, videoStateOverride = 0;
|
||||
|
||||
// cardId is the same as you can see in CARD telnet message
|
||||
struct ACLdata {
|
||||
byte cardId[7];
|
||||
char *nick;
|
||||
} ACL[] = {
|
||||
// the following include file contains lines like
|
||||
// { {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE}, "username" },
|
||||
/*!
|
||||
* The cardId is the same as you can see in CARD telnet message
|
||||
*
|
||||
* It's called broken, because we had broken reader that couldn't read 7-byte IDs.
|
||||
* I.e. the old reader could only use SELECT cascade 1, which begins with 0x88
|
||||
* cascading tag, thus we have only 3 bytes from 7-byte UIDs.
|
||||
*
|
||||
* So if we get a 7-byte ID, we must do "retarded search" for the 3-byte part.
|
||||
* If an ID in this struct contains 0x88 as third byte (index 2), it means it's
|
||||
* a card with 7 or 10 byte UID and begins with a cascading tag 0x88.
|
||||
*
|
||||
* Currently the bytes seem to be:
|
||||
*
|
||||
* case of 4-byte UID: 0x00, 0x00, UID1, UID2, UID3, UID4, BCC
|
||||
* case of 7-byte UID: 0xFF, 0x00, 0x88, UID1, UID2, UID3, BCC
|
||||
* case of 10-byte UID: ??? I don't think I actually saw a real card with
|
||||
* 10-byte UID, but it's in the NXP specs
|
||||
*
|
||||
*/
|
||||
typedef struct ACLdataBroken {
|
||||
byte cardId[7];
|
||||
const char *nick;
|
||||
} ACLRecordBroken;
|
||||
|
||||
/*!
|
||||
* List of ACLs included from a static array, see ACLRecordBroken for details.
|
||||
*/
|
||||
ACLRecordBroken ACL[] = {
|
||||
/* The following include file contains lines like
|
||||
* { {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE}, "username" },
|
||||
*/
|
||||
#include "cardids.h"
|
||||
};
|
||||
|
||||
/*! Structure for correct card UIDs */
|
||||
typedef struct ACLdataProper {
|
||||
uint8_t uidLength;
|
||||
uint8_t uid[10];
|
||||
const char *nick;
|
||||
} ACLRecordProper;
|
||||
|
||||
/*!
|
||||
* List of ACLs with proper full card's UID, included from another file.
|
||||
*
|
||||
* Keep the last element of array having uidLength of 0 last, it's a
|
||||
* terminator (so that we don't have to do sizeof arithmetic and guesstimating
|
||||
* whether aliasing will break it or not).
|
||||
*/
|
||||
ACLRecordProper ACLproper[] = {
|
||||
/* The following include file contains lines like
|
||||
* { 4, {0x35, 0xb0, 0x18, 0xd4}, "mifare_1" },
|
||||
* { 7, {0x04, 0xc2 0x4c, 0xe9, 0xad, 0x27, 0x80}, "ultralight_c" },
|
||||
*
|
||||
* Format of each array item is { UID_length, { UID_bytes }, nickname }
|
||||
*/
|
||||
#include "cardids_proper.h"
|
||||
{ 0, {0x00}, "terminator, don't delete this element!" }
|
||||
};
|
||||
|
||||
// Let's hope aliasing won't break this.
|
||||
// OMG why not some proper structures?
|
||||
#define ACL_COUNT (sizeof(ACL)/sizeof(ACLRecordBroken))
|
||||
|
||||
// ISO14443 cascading tag
|
||||
#define CASCADING_TAG 0x88
|
||||
|
||||
// comSerial for communication with the host
|
||||
#define comSerial Serial
|
||||
|
||||
// rfidSerial for communication with the RFID reader
|
||||
SoftwareSerial rfidSerial(rfidTx, rfidRx);
|
||||
// PN532 chip instance
|
||||
Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
|
||||
|
||||
#if MUSIC
|
||||
|
||||
|
@ -101,64 +180,163 @@ void openDoorForTime(int ms)
|
|||
digitalWrite(doorLock, LOW);
|
||||
}
|
||||
|
||||
void readCard()
|
||||
/*!
|
||||
* Will search for given card UID in the borken ACL list with truncated UIDs.
|
||||
*
|
||||
* @param uid UID of the card read
|
||||
* @param length length of the UID in bytes
|
||||
* @param acls list of ACLs in the old b0rken form
|
||||
* @param count of ACLs in the above array
|
||||
* @returns index into acls if found or -1 if not found
|
||||
*/
|
||||
int retardedACLSearch(const uint8_t *uid, uint8_t length, const struct ACLdataBroken *acls, int aclCount)
|
||||
{
|
||||
int idx = -1;
|
||||
|
||||
for(int i=0; i<aclCount; i++) {
|
||||
const ACLRecordBroken& acl = acls[i];
|
||||
|
||||
// Look for ISO14443 cascading tag 0x88 in third byte of the UID.
|
||||
// If it's present, then the UID has been truncated - only 3 bytes
|
||||
// are correct. Otherwise we got correct 4 byte UID.
|
||||
if (acl.cardId[2] == CASCADING_TAG) { // truncated UID
|
||||
if (memcmp(acl.cardId+3, uid, 3) == 0) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
} else { // full 4-byte UID
|
||||
if (memcmp(acl.cardId+2, uid, 4) == 0) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Will search for given card UID in the proper ACL list.
|
||||
*
|
||||
* @param uid UID of the card read
|
||||
* @param length length of the UID in bytes
|
||||
* @param acls list of proper ACLs (must contain the terminator as last element, see typedef above)
|
||||
* @returns index into acls if found or -1 if not found
|
||||
*/
|
||||
int properACLSearch(const uint8_t *uid, uint8_t length, const struct ACLdataProper *acls)
|
||||
{
|
||||
int idx = -1;
|
||||
|
||||
for(int i=0; ; i++) {
|
||||
const ACLRecordProper& acl = acls[i];
|
||||
|
||||
if (acl.uidLength == 0) {
|
||||
break; // reached terminator, no more elements
|
||||
}
|
||||
|
||||
if (length != acl.uidLength) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memcmp(uid, acl.uid, length) == 0) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*! Writes given UID encoded in hex to the serial specified. */
|
||||
void serialWriteUIDHex(const uint8_t *uid, uint8_t length)
|
||||
{
|
||||
for (int i=0; i<length; i++) {
|
||||
// why the fuck doesn't it have printf by default?
|
||||
if (uid[i] < 0x10) {
|
||||
comSerial.print("0");
|
||||
}
|
||||
comSerial.print(uid[i], HEX);
|
||||
}
|
||||
}
|
||||
|
||||
/*! Returns true iff we could read a card's UID.
|
||||
* That card UID is then looked up in the ACL array and response is sent
|
||||
* via UART to controlling computer (Raspberry, etc).
|
||||
*
|
||||
* Opens door for 5 seconds if the UID matched something in ACL array.
|
||||
*
|
||||
* Note: PN532 can read multiple cards in its field, but this is not supported
|
||||
* here (not necessary). The reader will pick one if there's more of them.
|
||||
*/
|
||||
bool readCardPN532()
|
||||
{
|
||||
uint8_t uid[10] = {0};
|
||||
uint8_t uidLength = 0;
|
||||
bool success;
|
||||
bool proper = false; // true will indicate we found UID in new non-borken ACL list
|
||||
int aclIdx = -1;
|
||||
|
||||
if (!pn532Working) {
|
||||
comSerial.write("NOCARD\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// read from PN532, change according to cardids, write result to comSerial
|
||||
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
|
||||
|
||||
if (!success) {
|
||||
// no card in reader field
|
||||
comSerial.write("NOCARD\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// try searching in proper ACL list first
|
||||
aclIdx = properACLSearch(uid, uidLength, ACLproper);
|
||||
|
||||
if (aclIdx >= 0) {
|
||||
proper = true;
|
||||
} else {
|
||||
// search for card UID in b0rken ACL database
|
||||
aclIdx = retardedACLSearch(uid, uidLength, ACL, ACL_COUNT);
|
||||
}
|
||||
|
||||
if (aclIdx < 0) {
|
||||
// unknown card ID
|
||||
comSerial.write("CARD UNKNOWN ");
|
||||
serialWriteUIDHex(uid, uidLength);
|
||||
comSerial.write("\n");
|
||||
playMelodyNak();
|
||||
delay(750);
|
||||
return false;
|
||||
}
|
||||
|
||||
// OK we got some known card, print its nick from respective ACL array
|
||||
comSerial.write("CARD ");
|
||||
comSerial.write(proper ? ACLproper[aclIdx].nick : ACL[aclIdx].nick);
|
||||
|
||||
if (printFullUID) {
|
||||
comSerial.write(" ");
|
||||
serialWriteUIDHex(uid, uidLength);
|
||||
}
|
||||
|
||||
// for debugging purposes - to know that we got the UID from proper ACL list
|
||||
if (printProper && proper) {
|
||||
comSerial.write(" proper");
|
||||
}
|
||||
|
||||
comSerial.write("\n");
|
||||
|
||||
openDoorForTime(5000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Set status led according to status, delat a bit. */
|
||||
void statusUpdate()
|
||||
{
|
||||
byte RequestCardStatus[] = { 0xAA, 0x00, 0x03, 0x25, 0x26, 0x00, 0x00, 0xBB };
|
||||
byte NoCardResponse[] = { 0xAA, 0x00, 0x02, 0x01, 0x83, 0x80, 0xBB };
|
||||
byte buf[16];
|
||||
int i;
|
||||
rfidSerial.listen();
|
||||
// write query to serial
|
||||
for (i = 0; i < 8; i++)
|
||||
rfidSerial.write((uint8_t)RequestCardStatus[i]);
|
||||
// wait for the result, while reblinking
|
||||
delay(100);
|
||||
digitalWrite(statusLed, statusState);
|
||||
delay(150);
|
||||
|
||||
// read input from serial into the buffer
|
||||
i = 0;
|
||||
while (rfidSerial.available() > 0) {
|
||||
if (i < sizeof(buf)) {
|
||||
buf[i] = rfidSerial.read();
|
||||
}
|
||||
++i;
|
||||
}
|
||||
// no card is detected
|
||||
if (!memcmp(buf, NoCardResponse, 7)) {
|
||||
comSerial.write("NOCARD\n");
|
||||
}
|
||||
|
||||
// card detected - message has form AA0006xxxxxxxxxxxxxxBB where xxx... is the card ID
|
||||
if (buf[0] == 0xAA && buf[1] == 0x00 && buf[2] == 0x06 && buf[10] == 0xBB) {
|
||||
bool known = false;
|
||||
// go through ACL
|
||||
for (int i = 0; i < sizeof(ACL)/sizeof(ACL[0]); ++i) {
|
||||
// if there is a match - print known card ...
|
||||
if (!memcmp(ACL[i].cardId, buf+3, 7)) {
|
||||
known = true;
|
||||
comSerial.write("CARD ");
|
||||
comSerial.write(ACL[i].nick);
|
||||
comSerial.write("\n");
|
||||
// ... and open door for 5s
|
||||
openDoorForTime(5000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// card was not found in the ACL
|
||||
if (!known) {
|
||||
comSerial.write("CARD UNKNOWN ");
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
if (buf[i+3] <= 0xF) comSerial.write("0");
|
||||
comSerial.print(buf[i+3], HEX);
|
||||
}
|
||||
comSerial.write("\n");
|
||||
playMelodyNak();
|
||||
}
|
||||
} else {
|
||||
// make cycle interval 1s
|
||||
delay(750);
|
||||
}
|
||||
}
|
||||
|
||||
void readSerial()
|
||||
|
@ -187,7 +365,17 @@ void setup()
|
|||
pinMode(videoBtn, INPUT);
|
||||
digitalWrite(videoBtn, HIGH);
|
||||
comSerial.begin(9600);
|
||||
rfidSerial.begin(9600);
|
||||
|
||||
nfc.begin();
|
||||
uint32_t versiondata = nfc.getFirmwareVersion();
|
||||
if (! versiondata) {
|
||||
comSerial.write("CARD READER BROKEN\n");
|
||||
pn532Working = false;
|
||||
} else {
|
||||
nfc.SAMConfig();
|
||||
nfc.setPassiveActivationRetries(pn532MaxRetries);
|
||||
pn532Working = true;
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
|
@ -204,11 +392,16 @@ void loop()
|
|||
|
||||
int doorOpen = digitalRead(magnetPin);
|
||||
|
||||
digitalWrite(statusLed, !statusState); // will be turned back in readCard()
|
||||
digitalWrite(statusLed, !statusState);
|
||||
digitalWrite(videoLed, videoState);
|
||||
|
||||
comSerial.print(statusState, DEC); comSerial.write(" ");
|
||||
comSerial.print(videoState, DEC); comSerial.write(" ");
|
||||
comSerial.print(doorOpen, DEC); comSerial.write(" ");
|
||||
readCard();
|
||||
|
||||
statusUpdate();
|
||||
|
||||
readCardPN532();
|
||||
readSerial();
|
||||
}
|
||||
|
||||
|
|
5
brmdoor/cardids.h.sample
Normal file
5
brmdoor/cardids.h.sample
Normal file
|
@ -0,0 +1,5 @@
|
|||
{ {0x00, 0x00, 0xDE, 0xEC, 0xE6, 0x3E, 0xEA}, "holland_chipkaart" },
|
||||
{ {0xFF, 0x00, 0x88, 0x04, 0x63, 0x19, 0xF6}, "desfire_3" }, //0x04, 0x63, 0x19, 0x82, 0xcc, 0x22, 0x80
|
||||
{ {0x00, 0x00, 0x35, 0xb0, 0x18, 0xd4, 0x49}, "mifare_1" },
|
||||
{ {0xFF, 0x00, 0x88, 0x04, 0xc2, 0x4c, 0x02}, "ultralight" } //04c24ce9ad2780
|
||||
|
5
brmdoor/cardids_proper.h.sample
Normal file
5
brmdoor/cardids_proper.h.sample
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Format of each array item is { UID_length, { UID_bytes }, nickname }
|
||||
// See definition of struct ACLdataProper in brmdoor.ino
|
||||
{ 4, {0x35, 0xb0, 0x18, 0xd4}, "mifare_1_proper" },
|
||||
{ 7, {0x04, 0xc2, 0x4c, 0xe9, 0xad, 0x27, 0x80}, "ultralight_proper" }, //04c24ce9ad2780
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue