diff options
Diffstat (limited to 'peripheral/libupm/src/pn532/pn532.h')
-rw-r--r-- | peripheral/libupm/src/pn532/pn532.h | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/peripheral/libupm/src/pn532/pn532.h b/peripheral/libupm/src/pn532/pn532.h new file mode 100644 index 0000000..206eb5b --- /dev/null +++ b/peripheral/libupm/src/pn532/pn532.h @@ -0,0 +1,505 @@ +/* + * Author: Jon Trulson <jtrulson@ics.com> + * Copyright (c) 2015 Intel Corporation. + * + * This code is heavily based on the Adafruit-PN532 library at + * https://github.com/adafruit/Adafruit-PN532, which is licensed under + * the BSD license. See upm/src/pn532/license.txt + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#pragma once + +#include <string.h> +#include <string> +#include <mraa/common.hpp> +#include <mraa/i2c.hpp> + +#include <mraa/gpio.hpp> + +#define PN532_I2C_BUS 0 +#define PN532_DEFAULT_I2C_ADDR (0x48 >> 1) + +#define PN532_PREAMBLE (0x00) +#define PN532_STARTCODE1 (0x00) +#define PN532_STARTCODE2 (0xFF) +#define PN532_POSTAMBLE (0x00) + +#define PN532_HOSTTOPN532 (0xD4) +#define PN532_PN532TOHOST (0xD5) + +namespace upm { + + /** + * @brief PN532 NFC/RFID reader/writer + * @defgroup pn532 libupm-pn532 + * @ingroup adafruit i2c rfid + */ + + /** + * @library pn532 + * @sensor pn532 + * @comname PN532 NFC/RFID reader/writer + * @type rfid + * @man adafruit + * @web http://www.adafruit.com/products/364 + * @con i2c + * + * @brief API for the PN532 based NFC/RFID reader/writer + * + * @image html pn532.jpg + * Identify a card and print out basic info + * @snippet pn532.cxx Interesting + * Add a URI to an already NDEF formatted ultralight or NTAG2XX tag + * @snippet pn532-writeurl.cxx Interesting + */ + class PN532 { + public: + + /** + * PN532 commands + */ + typedef enum { + CMD_DIAGNOSE = 0x00, + CMD_GETFIRMWAREVERSION = 0x02, + CMD_GETGENERALSTATUS = 0x04, + CMD_READREGISTER = 0x06, + CMD_WRITEREGISTER = 0x08, + CMD_READGPIO = 0x0C, + CMD_WRITEGPIO = 0x0E, + CMD_SETSERIALBAUDRATE = 0x10, + CMD_SETPARAMETERS = 0x12, + CMD_SAMCONFIGURATION = 0x14, + CMD_POWERDOWN = 0x16, + CMD_RFCONFIGURATION = 0x32, + CMD_RFREGULATIONTEST = 0x58, + CMD_INJUMPFORDEP = 0x56, + CMD_INJUMPFORPSL = 0x46, + CMD_INLISTPASSIVETARGET = 0x4A, + CMD_INATR = 0x50, + CMD_INPSL = 0x4E, + CMD_INDATAEXCHANGE = 0x40, + CMD_INCOMMUNICATETHRU = 0x42, + CMD_INDESELECT = 0x44, + CMD_INRELEASE = 0x52, + CMD_INSELECT = 0x54, + CMD_INAUTOPOLL = 0x60, + CMD_TGINITASTARGET = 0x8C, + CMD_TGSETGENERALBYTES = 0x92, + CMD_TGGETDATA = 0x86, + CMD_TGSETDATA = 0x8E, + CMD_TGSETMETADATA = 0x94, + CMD_TGGETINITIATORCOMMAND = 0x88, + CMD_TGRESPONSETOINITIATOR = 0x90, + CMD_TGGETTARGETSTATUS = 0x8A + } PN532_CMD_T; + + /** + * Response bytes + */ + typedef enum { + RSP_INDATAEXCHANGE = 0x41, + RSP_INLISTPASSIVETARGET = 0x4B + } PN532_RSP_T; + + /** + * MIFARE commands + */ + typedef enum { + MIFARE_CMD_AUTH_A = 0x60, + MIFARE_CMD_AUTH_B = 0x61, + MIFARE_CMD_READ = 0x30, + MIFARE_CMD_WRITE = 0xA0, + MIFARE_CMD_TRANSFER = 0xB0, + MIFARE_CMD_DECREMENT = 0xC0, + MIFARE_CMD_INCREMENT = 0xC1, + MIFARE_CMD_STORE = 0xC2, + MIFARE_ULTRALIGHT_CMD_WRITE = 0xA2 + } MIFARE_CMD_T; + + /** + * NDEF prefixes + */ + typedef enum { + NDEF_URIPREFIX_NONE = 0x00, + NDEF_URIPREFIX_HTTP_WWWDOT = 0x01, + NDEF_URIPREFIX_HTTPS_WWWDOT = 0x02, + NDEF_URIPREFIX_HTTP = 0x03, + NDEF_URIPREFIX_HTTPS = 0x04, + NDEF_URIPREFIX_TEL = 0x05, + NDEF_URIPREFIX_MAILTO = 0x06, + NDEF_URIPREFIX_FTP_ANONAT = 0x07, + NDEF_URIPREFIX_FTP_FTPDOT = 0x08, + NDEF_URIPREFIX_FTPS = 0x09, + NDEF_URIPREFIX_SFTP = 0x0A, + NDEF_URIPREFIX_SMB = 0x0B, + NDEF_URIPREFIX_NFS = 0x0C, + NDEF_URIPREFIX_FTP = 0x0D, + NDEF_URIPREFIX_DAV = 0x0E, + NDEF_URIPREFIX_NEWS = 0x0F, + NDEF_URIPREFIX_TELNET = 0x10, + NDEF_URIPREFIX_IMAP = 0x11, + NDEF_URIPREFIX_RTSP = 0x12, + NDEF_URIPREFIX_URN = 0x13, + NDEF_URIPREFIX_POP = 0x14, + NDEF_URIPREFIX_SIP = 0x15, + NDEF_URIPREFIX_SIPS = 0x16, + NDEF_URIPREFIX_TFTP = 0x17, + NDEF_URIPREFIX_BTSPP = 0x18, + NDEF_URIPREFIX_BTL2CAP = 0x19, + NDEF_URIPREFIX_BTGOEP = 0x1A, + NDEF_URIPREFIX_TCPOBEX = 0x1B, + NDEF_URIPREFIX_IRDAOBEX = 0x1C, + NDEF_URIPREFIX_FILE = 0x1D, + NDEF_URIPREFIX_URN_EPC_ID = 0x1E, + NDEF_URIPREFIX_URN_EPC_TAG = 0x1F, + NDEF_URIPREFIX_URN_EPC_PAT = 0x20, + NDEF_URIPREFIX_URN_EPC_RAW = 0x21, + NDEF_URIPREFIX_URN_EPC = 0x22, + NDEF_URIPREFIX_URN_NFC = 0x23 + } NDEF_URI_T; + + /** + * Card baud rates + */ + typedef enum { + BAUD_MIFARE_ISO14443A = 0x00 // 106 Kbit/s + } BAUD_T; + + + /** + * Tag types + */ + typedef enum { + TAG_TYPE_UNKNOWN = 0, + TAG_TYPE_MIFARE_CLASSIC = 1, + TAG_TYPE_NFC2 = 2 /* ultralight or NTAG2XX */ + } TAG_TYPE_T; + + /** + * pn532 constructor + * + * @param irq pin to use for IRQ + * @param reset reset pin + * @param bus i2c bus to use + * @param address the address for this device + */ + PN532(int irq, int reset, int bus=PN532_I2C_BUS, + uint8_t address=PN532_DEFAULT_I2C_ADDR); + + /** + * PN532 Destructor + */ + ~PN532(); + + /** + * set up initial values and start operation + * + * @return true if successful + */ + bool init(); + + /** + * Checks the firmware version of the PN5xx chip + * + * @return the chip's firmware version and ID + */ + uint32_t getFirmwareVersion(); + + /** + * sends a command and waits a specified period for the ACK + * + * @param cmd Pointer to the command buffer + * @param cmdlen the size of the command in bytes + * @param timeout timeout before giving up (in ms) + * + * @return true if everything is OK, false if timeout occured + * before an ACK was recieved + */ + bool sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, + uint16_t timeout=1000); + + /** + * configures the SAM (Secure Access Module) + * + * @return true if successfully configured + */ + bool SAMConfig(void); + + /** + * sets the MxRtyPassiveActivation byte of the RFConfiguration + * register. By default the pn532 will retry indefinitely. + * + * @param maxRetries 0xFF to wait forever, 0x00..0xFE to timeout + * after maxRetries. 0x00 means try once, with no retries on failure. + * + * @return true if everything executed properly, false for an error + */ + bool setPassiveActivationRetries(uint8_t maxRetries); + + /** + * waits for an ISO14443A target to enter the field + * + * @param cardbaudbate baud rate of the card, one of the BAUD_T values + * @param uid Pointer to the array that will be populated with the + * cards UID, up to 7 bytes + * @param uidLength Pointer to the variable that will hold the + * length of the card's UID. + * @param timeout the number of milliseconds to wait + * + * @return true if everything executed properly, false for an error + */ + bool readPassiveTargetID(BAUD_T cardbaudrate, uint8_t * uid, + uint8_t * uidLength, uint16_t timeout); + + /** + * exchanges an APDU (Application Protocol Data Unit) 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 + * + * @return true if everything executed properly, false for an error + */ + bool inDataExchange(uint8_t * send, uint8_t sendLength, + uint8_t * response, uint8_t * responseLength); + + /** + * 'InLists' a passive target. PN532 acting as reader/initiator, + * peer acting as card/responder. + * + * @return true if everything executed properly, false for an error + */ + bool inListPassiveTarget(); + + /** + * Indicates whether the specified block number is the first block + * in the sector (block 0 relative to the current sector) + * + * @return true if it's the first block, false otherwise + */ + bool mifareclassic_IsFirstBlock (uint32_t uiBlock); + + /** + * indicates whether the specified block number is the sector trailer + * + * @return true if it's the trailer block, false otherwise + */ + bool mifareclassic_IsTrailerBlock (uint32_t uiBlock); + + /** + * 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 byte + * key value + * + * @return true if everything executed properly, false for an error + */ + bool mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen, + uint32_t blockNumber, + uint8_t keyNumber, + uint8_t * keyData); + + /** + * tries to read an entire 16-byte data block at the specified block + * address. + * + * @param blockNumber The block number to read (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) + * + * @return true if everything executed properly, false for an error + */ + bool mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data); + + /** + * tries to write an entire 16-byte data block at the specified block + * address. + * + * @param blockNumber The block number to write. (0..63 for + * 1KB cards, and 0..255 for 4KB cards). + * @param data The byte array that contains the data to write. + * + * @returns true if everything executed properly, false for an error + */ + bool mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data); + + /** + * formats a Mifare Classic card to store NDEF Records + * + * @return true if everything executed properly, false for an error + */ + bool mifareclassic_FormatNDEF (void); + + /** + * writes an NDEF URI Record to the specified sector (1..15) + * + * Note that this function assumes that the Mifare Classic card is + * already formatted to work as an "NFC Forum Tag" and uses a MAD1 + * file system. You can use the NXP TagWriter app on Android to + * properly format cards for this. + * + * @param sectorNumber The sector that the URI record should be written + * to (can be 1..15 for a 1K card) + * @param uriIdentifier The uri identifier code (one of the NDEF_URI_T + * values + * @param url the uri text to write (max 38 characters). + * + * @return true if everything executed properly, false for an error + */ + bool mifareclassic_WriteNDEFURI (uint8_t sectorNumber, + NDEF_URI_T uriIdentifier, + const char * url); + + /** + * read an entire 4-byte page at the specified address + * + * @param page The page number (0..63 in most cases) + * @param buffer Pointer to the byte array that will hold the + * retrieved data (if any) + * + * @return true if everything executed properly, false for an error + */ + bool ntag2xx_ReadPage (uint8_t page, uint8_t * buffer); + + /** + * write an entire 4-byte page at the specified block address + * + * @param page The page number to write. (0..63 for most cases) + * @param data The byte array that contains the data to write. + * Should be exactly 4 bytes long. + * + * @return true if everything executed properly, false for an error + */ + bool ntag2xx_WritePage (uint8_t page, uint8_t * data); + + /** + * writes an NDEF URI Record starting at the specified page (4..nn) + * + * Note that this function assumes that the NTAG2xx card is + * already formatted to work as an "NFC Forum Tag". + * + * @param uriIdentifier The uri identifier code (one of the NDEF_URI_T + * values + * @param url The uri text to write (null-terminated string). + * @param dataLen The size of the data area for overflow checks. + * + * @return true if everything executed properly, false for an error + */ + bool ntag2xx_WriteNDEFURI (NDEF_URI_T uriIdentifier, char * url, + uint8_t dataLen); + + /** + * return the ATQA (Answer to Request Acknowlege) value. This + * value is only valid after a successfull call to + * readPassiveTargetID() + * + * @return ATQA value + */ + uint16_t getATQA() { return m_ATQA; }; + + /** + * return the SAK (Select Acknowlege) value. This + * value is only valid after a successfull call to + * readPassiveTargetID() + * + * @return SAK value + */ + uint8_t getSAK() { return m_SAK; }; + + /** + * provide public access to the class's MRAA i2C context for + * direct user access + * + * @return a reference to the class i2c context + */ + mraa::I2c& i2cContext() { return m_i2c; }; + + /** + * enable or disable debugging output for pn532 related operations + * + * @param enable true to enabloe debug output, false to disable + */ + void pn532Debug(bool enable) { m_pn532Debug = enable; }; + + /** + * enable or disable debugging output for mifare related operations + * + * @param enable true to enabloe debug output, false to disable + */ + + void mifareDebug(bool enable) { m_mifareDebug = enable; }; + + /** + * try to determine the tag type + * + * @return one of the TAG_TYPE_T values + */ + TAG_TYPE_T tagType(); + + protected: + mraa::I2c m_i2c; + mraa::Gpio m_gpioIRQ; + mraa::Gpio m_gpioReset; + + bool readAck(); + bool isReady(); + bool waitForReady(uint16_t timeout); + void readData(uint8_t* buff, uint8_t n); + void writeCommand(uint8_t* cmd, uint8_t cmdlen); + + private: + static void dataReadyISR(void *ctx); + bool m_isrInstalled; + volatile bool m_irqRcvd; + + uint8_t m_addr; + + uint8_t m_uid[7]; // ISO14443A uid + uint8_t m_uidLen; // uid len + uint8_t m_key[6]; // Mifare Classic key + uint8_t m_inListedTag; // Tg number of inlisted tag. + + uint16_t m_ATQA; // ATQA (Answer to Request Acknowlege - ISO14443) + // for currently inlisted card + uint8_t m_SAK; // SAK (Select Acknowlege) + // for currently inlisted card + + // debugables + bool m_pn532Debug; + bool m_mifareDebug; + }; +} + + |