1 /*
2  * Author: Jon Trulson <jtrulson@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      */
getATQA()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      */
getSAK()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      */
i2cContext()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      */
pn532Debug(bool enable)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 
mifareDebug(bool enable)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