Home | History | Annotate | Download | only in pn532
      1 /*
      2  * Author: Jon Trulson <jtrulson (at) ics.com>
      3  * Copyright (c) 2015 Intel Corporation.
      4  *
      5  * This code is heavily based on the Adafruit-PN532 library at
      6  * https://github.com/adafruit/Adafruit-PN532, which is licensed under
      7  * the BSD license. See upm/src/pn532/license.txt
      8  *
      9  * Permission is hereby granted, free of charge, to any person obtaining
     10  * a copy of this software and associated documentation files (the
     11  * "Software"), to deal in the Software without restriction, including
     12  * without limitation the rights to use, copy, modify, merge, publish,
     13  * distribute, sublicense, and/or sell copies of the Software, and to
     14  * permit persons to whom the Software is furnished to do so, subject to
     15  * the following conditions:
     16  *
     17  * The above copyright notice and this permission notice shall be
     18  * included in all copies or substantial portions of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     24  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     25  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     26  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     27  */
     28 
     29 
     30 #pragma once
     31 
     32 #include <string.h>
     33 #include <string>
     34 #include <mraa/common.hpp>
     35 #include <mraa/i2c.hpp>
     36 
     37 #include <mraa/gpio.hpp>
     38 
     39 #define PN532_I2C_BUS 0
     40 #define PN532_DEFAULT_I2C_ADDR (0x48 >> 1)
     41 
     42 #define PN532_PREAMBLE                      (0x00)
     43 #define PN532_STARTCODE1                    (0x00)
     44 #define PN532_STARTCODE2                    (0xFF)
     45 #define PN532_POSTAMBLE                     (0x00)
     46 
     47 #define PN532_HOSTTOPN532                   (0xD4)
     48 #define PN532_PN532TOHOST                   (0xD5)
     49 
     50 namespace upm {
     51 
     52   /**
     53    * @brief PN532 NFC/RFID reader/writer
     54    * @defgroup pn532 libupm-pn532
     55    * @ingroup adafruit i2c rfid
     56    */
     57 
     58   /**
     59    * @library pn532
     60    * @sensor pn532
     61    * @comname PN532 NFC/RFID reader/writer
     62    * @type rfid
     63    * @man adafruit
     64    * @web http://www.adafruit.com/products/364
     65    * @con i2c
     66    *
     67    * @brief API for the PN532 based NFC/RFID reader/writer
     68    *
     69    * Identify a card and print out basic info
     70    * @snippet pn532.cxx Interesting
     71    * Add a URI to an already NDEF formatted ultralight or NTAG2XX tag
     72    * @snippet pn532-writeurl.cxx Interesting
     73    */
     74   class PN532 {
     75   public:
     76 
     77     /**
     78      * PN532 commands
     79      */
     80     typedef enum {
     81       CMD_DIAGNOSE              = 0x00,
     82       CMD_GETFIRMWAREVERSION    = 0x02,
     83       CMD_GETGENERALSTATUS      = 0x04,
     84       CMD_READREGISTER          = 0x06,
     85       CMD_WRITEREGISTER         = 0x08,
     86       CMD_READGPIO              = 0x0C,
     87       CMD_WRITEGPIO             = 0x0E,
     88       CMD_SETSERIALBAUDRATE     = 0x10,
     89       CMD_SETPARAMETERS         = 0x12,
     90       CMD_SAMCONFIGURATION      = 0x14,
     91       CMD_POWERDOWN             = 0x16,
     92       CMD_RFCONFIGURATION       = 0x32,
     93       CMD_RFREGULATIONTEST      = 0x58,
     94       CMD_INJUMPFORDEP          = 0x56,
     95       CMD_INJUMPFORPSL          = 0x46,
     96       CMD_INLISTPASSIVETARGET   = 0x4A,
     97       CMD_INATR                 = 0x50,
     98       CMD_INPSL                 = 0x4E,
     99       CMD_INDATAEXCHANGE        = 0x40,
    100       CMD_INCOMMUNICATETHRU     = 0x42,
    101       CMD_INDESELECT            = 0x44,
    102       CMD_INRELEASE             = 0x52,
    103       CMD_INSELECT              = 0x54,
    104       CMD_INAUTOPOLL            = 0x60,
    105       CMD_TGINITASTARGET        = 0x8C,
    106       CMD_TGSETGENERALBYTES     = 0x92,
    107       CMD_TGGETDATA             = 0x86,
    108       CMD_TGSETDATA             = 0x8E,
    109       CMD_TGSETMETADATA         = 0x94,
    110       CMD_TGGETINITIATORCOMMAND = 0x88,
    111       CMD_TGRESPONSETOINITIATOR = 0x90,
    112       CMD_TGGETTARGETSTATUS     = 0x8A
    113     } PN532_CMD_T;
    114 
    115     /**
    116      * Response bytes
    117      */
    118     typedef enum {
    119       RSP_INDATAEXCHANGE        = 0x41,
    120       RSP_INLISTPASSIVETARGET   = 0x4B
    121     } PN532_RSP_T;
    122 
    123     /**
    124      * MIFARE commands
    125      */
    126     typedef enum {
    127       MIFARE_CMD_AUTH_A                   = 0x60,
    128       MIFARE_CMD_AUTH_B                   = 0x61,
    129       MIFARE_CMD_READ                     = 0x30,
    130       MIFARE_CMD_WRITE                    = 0xA0,
    131       MIFARE_CMD_TRANSFER                 = 0xB0,
    132       MIFARE_CMD_DECREMENT                = 0xC0,
    133       MIFARE_CMD_INCREMENT                = 0xC1,
    134       MIFARE_CMD_STORE                    = 0xC2,
    135       MIFARE_ULTRALIGHT_CMD_WRITE         = 0xA2
    136     } MIFARE_CMD_T;
    137 
    138     /**
    139      * NDEF prefixes
    140      */
    141     typedef enum {
    142       NDEF_URIPREFIX_NONE                 = 0x00,
    143       NDEF_URIPREFIX_HTTP_WWWDOT          = 0x01,
    144       NDEF_URIPREFIX_HTTPS_WWWDOT         = 0x02,
    145       NDEF_URIPREFIX_HTTP                 = 0x03,
    146       NDEF_URIPREFIX_HTTPS                = 0x04,
    147       NDEF_URIPREFIX_TEL                  = 0x05,
    148       NDEF_URIPREFIX_MAILTO               = 0x06,
    149       NDEF_URIPREFIX_FTP_ANONAT           = 0x07,
    150       NDEF_URIPREFIX_FTP_FTPDOT           = 0x08,
    151       NDEF_URIPREFIX_FTPS                 = 0x09,
    152       NDEF_URIPREFIX_SFTP                 = 0x0A,
    153       NDEF_URIPREFIX_SMB                  = 0x0B,
    154       NDEF_URIPREFIX_NFS                  = 0x0C,
    155       NDEF_URIPREFIX_FTP                  = 0x0D,
    156       NDEF_URIPREFIX_DAV                  = 0x0E,
    157       NDEF_URIPREFIX_NEWS                 = 0x0F,
    158       NDEF_URIPREFIX_TELNET               = 0x10,
    159       NDEF_URIPREFIX_IMAP                 = 0x11,
    160       NDEF_URIPREFIX_RTSP                 = 0x12,
    161       NDEF_URIPREFIX_URN                  = 0x13,
    162       NDEF_URIPREFIX_POP                  = 0x14,
    163       NDEF_URIPREFIX_SIP                  = 0x15,
    164       NDEF_URIPREFIX_SIPS                 = 0x16,
    165       NDEF_URIPREFIX_TFTP                 = 0x17,
    166       NDEF_URIPREFIX_BTSPP                = 0x18,
    167       NDEF_URIPREFIX_BTL2CAP              = 0x19,
    168       NDEF_URIPREFIX_BTGOEP               = 0x1A,
    169       NDEF_URIPREFIX_TCPOBEX              = 0x1B,
    170       NDEF_URIPREFIX_IRDAOBEX             = 0x1C,
    171       NDEF_URIPREFIX_FILE                 = 0x1D,
    172       NDEF_URIPREFIX_URN_EPC_ID           = 0x1E,
    173       NDEF_URIPREFIX_URN_EPC_TAG          = 0x1F,
    174       NDEF_URIPREFIX_URN_EPC_PAT          = 0x20,
    175       NDEF_URIPREFIX_URN_EPC_RAW          = 0x21,
    176       NDEF_URIPREFIX_URN_EPC              = 0x22,
    177       NDEF_URIPREFIX_URN_NFC              = 0x23
    178     } NDEF_URI_T;
    179 
    180     /**
    181      * Card baud rates
    182      */
    183     typedef enum {
    184       BAUD_MIFARE_ISO14443A               = 0x00 // 106 Kbit/s
    185     } BAUD_T;
    186 
    187 
    188     /**
    189      * Tag types
    190      */
    191     typedef enum {
    192       TAG_TYPE_UNKNOWN                    = 0,
    193       TAG_TYPE_MIFARE_CLASSIC             = 1,
    194       TAG_TYPE_NFC2                       = 2 /* ultralight or NTAG2XX */
    195     } TAG_TYPE_T;
    196 
    197     /**
    198      * pn532 constructor
    199      *
    200      * @param irq pin to use for IRQ
    201      * @param reset reset pin
    202      * @param bus i2c bus to use
    203      * @param address the address for this device
    204      */
    205     PN532(int irq, int reset, int bus=PN532_I2C_BUS,
    206           uint8_t address=PN532_DEFAULT_I2C_ADDR);
    207 
    208     /**
    209      * PN532 Destructor
    210      */
    211     ~PN532();
    212 
    213     /**
    214      * set up initial values and start operation
    215      *
    216      * @return true if successful
    217      */
    218     bool init();
    219 
    220     /**
    221      * Checks the firmware version of the PN5xx chip
    222      *
    223      * @return the chip's firmware version and ID
    224     */
    225     uint32_t getFirmwareVersion();
    226 
    227     /**
    228      * sends a command and waits a specified period for the ACK
    229      *
    230      * @param  cmd       Pointer to the command buffer
    231      * @param  cmdlen    the size of the command in bytes
    232      * @param  timeout   timeout before giving up (in ms)
    233      *
    234      * @return true if everything is OK, false if timeout occured
    235      * before an ACK was recieved
    236      */
    237     bool sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen,
    238                              uint16_t timeout=1000);
    239 
    240     /**
    241      * configures the SAM (Secure Access Module)
    242      *
    243      * @return true if successfully configured
    244      */
    245     bool SAMConfig(void);
    246 
    247     /**
    248      * sets the MxRtyPassiveActivation byte of the RFConfiguration
    249      * register.  By default the pn532 will retry indefinitely.
    250      *
    251      * @param  maxRetries 0xFF to wait forever, 0x00..0xFE to timeout
    252      * after maxRetries.  0x00 means try once, with no retries on failure.
    253      *
    254      * @return true if everything executed properly, false for an error
    255      */
    256     bool setPassiveActivationRetries(uint8_t maxRetries);
    257 
    258     /**
    259      *  waits for an ISO14443A target to enter the field
    260      *
    261      * @param  cardbaudbate  baud rate of the card, one of the BAUD_T values
    262      * @param  uid Pointer to the array that will be populated with the
    263      * cards UID, up to 7 bytes
    264      * @param  uidLength Pointer to the variable that will hold the
    265      * length of the card's UID.
    266      * @param timeout the number of milliseconds to wait
    267      *
    268      * @return true if everything executed properly, false for an error
    269      */
    270     bool readPassiveTargetID(BAUD_T cardbaudrate, uint8_t * uid,
    271                              uint8_t * uidLength, uint16_t timeout);
    272 
    273     /**
    274      * exchanges an APDU (Application Protocol Data Unit) with the
    275      * currently inlisted peer
    276      *
    277      * @param  send            Pointer to data to send
    278      * @param  sendLength      Length of the data to send
    279      * @param  response        Pointer to response data
    280      * @param  responseLength  Pointer to the response data length
    281      *
    282      * @return true if everything executed properly, false for an error
    283      */
    284     bool inDataExchange(uint8_t * send, uint8_t sendLength,
    285                         uint8_t * response, uint8_t * responseLength);
    286 
    287     /**
    288      * 'InLists' a passive target. PN532 acting as reader/initiator,
    289      * peer acting as card/responder.
    290      *
    291      * @return true if everything executed properly, false for an error
    292      */
    293     bool inListPassiveTarget();
    294 
    295     /**
    296      *  Indicates whether the specified block number is the first block
    297      *  in the sector (block 0 relative to the current sector)
    298      *
    299      * @return true if it's the first block, false otherwise
    300      */
    301     bool mifareclassic_IsFirstBlock (uint32_t uiBlock);
    302 
    303     /**
    304      * indicates whether the specified block number is the sector trailer
    305      *
    306      * @return true if it's the trailer block, false otherwise
    307      */
    308     bool mifareclassic_IsTrailerBlock (uint32_t uiBlock);
    309 
    310     /**
    311      * tries to authenticate a block of memory on a MIFARE card using the
    312      * INDATAEXCHANGE command.  See section 7.3.8 of the PN532 User Manual
    313      * for more information on sending MIFARE and other commands.
    314      *
    315      * @param  uid           Pointer to a byte array containing the card UID
    316      * @param  uidLen        The length (in bytes) of the card's UID (Should
    317      * be 4 for MIFARE Classic)
    318      * @param  blockNumber   The block number to authenticate.  (0..63 for
    319      * 1KB cards, and 0..255 for 4KB cards).
    320      * @param  keyNumber     Which key type to use during authentication
    321      * (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
    322      * @param  keyData       Pointer to a byte array containing the 6 byte
    323      * key value
    324      *
    325      * @return true if everything executed properly, false for an error
    326      */
    327     bool mifareclassic_AuthenticateBlock (uint8_t * uid, uint8_t uidLen,
    328                                           uint32_t blockNumber,
    329                                           uint8_t keyNumber,
    330                                           uint8_t * keyData);
    331 
    332     /**
    333      *  tries to read an entire 16-byte data block at the specified block
    334      *  address.
    335      *
    336      *  @param  blockNumber   The block number to read  (0..63 for
    337      *  1KB cards, and 0..255 for 4KB cards).
    338      *  @param  data          Pointer to the byte array that will hold the
    339      *  retrieved data (if any)
    340      *
    341      *  @return true if everything executed properly, false for an error
    342      */
    343     bool mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data);
    344 
    345     /**
    346      *  tries to write an entire 16-byte data block at the specified block
    347      *  address.
    348      *
    349      *  @param  blockNumber   The block number to write.  (0..63 for
    350      *  1KB cards, and 0..255 for 4KB cards).
    351      *  @param  data          The byte array that contains the data to write.
    352      *
    353      *  @returns true if everything executed properly, false for an error
    354      */
    355     bool mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data);
    356 
    357     /**
    358      *  formats a Mifare Classic card to store NDEF Records
    359      *
    360      *  @return true if everything executed properly, false for an error
    361      */
    362     bool mifareclassic_FormatNDEF (void);
    363 
    364     /**
    365      *  writes an NDEF URI Record to the specified sector (1..15)
    366      *
    367      *  Note that this function assumes that the Mifare Classic card is
    368      *  already formatted to work as an "NFC Forum Tag" and uses a MAD1
    369      *  file system.  You can use the NXP TagWriter app on Android to
    370      *  properly format cards for this.
    371      *
    372      * @param  sectorNumber  The sector that the URI record should be written
    373      * to (can be 1..15 for a 1K card)
    374      * @param  uriIdentifier The uri identifier code (one of the NDEF_URI_T
    375      * values
    376      * @param  url the uri text to write (max 38 characters).
    377      *
    378      * @return true if everything executed properly, false for an error
    379      */
    380     bool mifareclassic_WriteNDEFURI (uint8_t sectorNumber,
    381                                      NDEF_URI_T uriIdentifier,
    382                                      const char * url);
    383 
    384     /**
    385      * read an entire 4-byte page at the specified address
    386      *
    387      * @param  page        The page number (0..63 in most cases)
    388      * @param  buffer      Pointer to the byte array that will hold the
    389      * retrieved data (if any)
    390      *
    391      * @return true if everything executed properly, false for an error
    392      */
    393     bool ntag2xx_ReadPage (uint8_t page, uint8_t * buffer);
    394 
    395     /**
    396      *  write an entire 4-byte page at the specified block address
    397      *
    398      * @param  page          The page number to write.  (0..63 for most cases)
    399      * @param  data          The byte array that contains the data to write.
    400      * Should be exactly 4 bytes long.
    401      *
    402      * @return true if everything executed properly, false for an error
    403      */
    404     bool ntag2xx_WritePage (uint8_t page, uint8_t * data);
    405 
    406     /**
    407      * writes an NDEF URI Record starting at the specified page (4..nn)
    408      *
    409      * Note that this function assumes that the NTAG2xx card is
    410      * already formatted to work as an "NFC Forum Tag".
    411      *
    412      * @param  uriIdentifier The uri identifier code (one of the NDEF_URI_T
    413      * values
    414      * @param  url           The uri text to write (null-terminated string).
    415      * @param  dataLen       The size of the data area for overflow checks.
    416      *
    417      * @return true if everything executed properly, false for an error
    418      */
    419     bool ntag2xx_WriteNDEFURI (NDEF_URI_T uriIdentifier, char * url,
    420                                uint8_t dataLen);
    421 
    422     /**
    423      * return the ATQA (Answer to Request Acknowlege) value.  This
    424      * value is only valid after a successfull call to
    425      * readPassiveTargetID()
    426      *
    427      * @return ATQA value
    428      */
    429     uint16_t getATQA() { return m_ATQA; };
    430 
    431     /**
    432      * return the SAK (Select Acknowlege) value.  This
    433      * value is only valid after a successfull call to
    434      * readPassiveTargetID()
    435      *
    436      * @return SAK value
    437      */
    438     uint8_t getSAK() { return m_SAK; };
    439 
    440     /**
    441      * provide public access to the class's MRAA i2C context for
    442      * direct user access
    443      *
    444      * @return a reference to the class i2c context
    445      */
    446     mraa::I2c& i2cContext() { return m_i2c; };
    447 
    448     /**
    449      * enable or disable debugging output for pn532 related operations
    450      *
    451      * @param enable true to enabloe debug output, false to disable
    452      */
    453     void pn532Debug(bool enable) { m_pn532Debug = enable; };
    454 
    455     /**
    456      * enable or disable debugging output for mifare related operations
    457      *
    458      * @param enable true to enabloe debug output, false to disable
    459      */
    460 
    461     void mifareDebug(bool enable) { m_mifareDebug = enable; };
    462 
    463     /**
    464      * try to determine the tag type
    465      *
    466      * @return one of the TAG_TYPE_T values
    467      */
    468     TAG_TYPE_T tagType();
    469 
    470   protected:
    471     mraa::I2c m_i2c;
    472     mraa::Gpio m_gpioIRQ;
    473     mraa::Gpio m_gpioReset;
    474 
    475     bool readAck();
    476     bool isReady();
    477     bool waitForReady(uint16_t timeout);
    478     void readData(uint8_t* buff, uint8_t n);
    479     void writeCommand(uint8_t* cmd, uint8_t cmdlen);
    480 
    481   private:
    482     static void dataReadyISR(void *ctx);
    483     bool m_isrInstalled;
    484     volatile bool m_irqRcvd;
    485 
    486     uint8_t m_addr;
    487 
    488     uint8_t m_uid[7];       // ISO14443A uid
    489     uint8_t m_uidLen;       // uid len
    490     uint8_t m_key[6];       // Mifare Classic key
    491     uint8_t m_inListedTag;  // Tg number of inlisted tag.
    492 
    493     uint16_t m_ATQA;        // ATQA (Answer to Request Acknowlege - ISO14443)
    494                             // for currently inlisted card
    495     uint8_t m_SAK;          // SAK (Select Acknowlege)
    496                             // for currently inlisted card
    497 
    498     // debugables
    499     bool m_pn532Debug;
    500     bool m_mifareDebug;
    501   };
    502 }
    503 
    504 
    505