Home | History | Annotate | Download | only in sm130
      1 /*
      2  * Author: Jon Trulson <jtrulson (at) ics.com>
      3  * Copyright (c) 2015 Intel Corporation.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be
     14  * included in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 #pragma once
     25 
     26 #include <string>
     27 #include <iostream>
     28 
     29 #include <stdlib.h>
     30 #include <stdint.h>
     31 #include <unistd.h>
     32 #include <string.h>
     33 #include <sys/time.h>
     34 #include <sys/select.h>
     35 #include <sys/types.h>
     36 #include <sys/stat.h>
     37 
     38 #include <mraa/common.hpp>
     39 #include <mraa/uart.hpp>
     40 #include <mraa/gpio.hpp>
     41 
     42 #define SM130_DEFAULT_UART 0
     43 #define SM130_DEFAULT_RESET_PIN 13
     44 
     45 namespace upm {
     46 
     47   /**
     48    * @brief SM130 RFID Reader Module library
     49    * @defgroup sm130 libupm-sm130
     50    * @ingroup sparkfun uart gpio rfid
     51    */
     52 
     53   /**
     54    * @library sm130
     55    * @sensor sm130
     56    * @comname SM130 RFID Reader
     57    * @type rfid
     58    * @man sparkfun
     59    * @web https://www.sparkfun.com/products/10126
     60    * @con uart gpio
     61    *
     62    * @brief API for the SM130 RFID Reader Module
     63    *
     64    * This module defines the SM130 interface for the sm130 RFID library
     65    *
     66    * This module was developed using an SM130 and a Sparkfun RFID
     67    * Evaluation shield using a UART for communications.  It should be
     68    * fairly trivial to add support for I2C communication in the
     69    * future, if you have the correct firmware on the SM130.
     70    *
     71    * @image html sm130.jpg
     72    * <br><em>SM130 RFID Reader image provided by SparkFun* under
     73    * <a href=https://creativecommons.org/licenses/by-nc-sa/3.0/>
     74    * CC BY-NC-SA-3.0</a>.</em>
     75    *
     76    * @snippet sm130.cxx Interesting
     77    */
     78 
     79   class SM130 {
     80 
     81   public:
     82 
     83     // Valid commands
     84     typedef enum {
     85       CMD_RESET                  = 0x80,
     86       CMD_VERSION                = 0x81,
     87       CMD_SEEK_TAG               = 0x82,
     88       CMD_SELECT_TAG             = 0x83,
     89       CMD_AUTHENTICATE           = 0x85,
     90       CMD_READ16                 = 0x86,
     91       CMD_READ_VALUE             = 0x87,
     92       CMD_WRITE16                = 0x89,
     93       CMD_WRITE_VALUE            = 0x8a,
     94       CMD_WRITE4                 = 0x8b,
     95       CMD_WRITE_KEY              = 0x8c,
     96       CMD_INC_VALUE              = 0x8d,
     97       CMD_DEC_VALUE              = 0x8e,
     98       CMD_ANTENNA_POWER          = 0x90,
     99       CMD_READ_PORT              = 0x91,
    100       CMD_WRITE_PORT             = 0x92,
    101       CMD_HALT_TAG               = 0x93,
    102       CMD_SET_BAUD               = 0x94,
    103       CMD_SLEEP                  = 0x96
    104     } CMD_T;
    105 
    106     // valid tag types.
    107     typedef enum {
    108       TAG_NONE                   = 0x00, // error/invalid
    109 
    110       TAG_MIFARE_ULTRALIGHT      = 0x01,
    111       TAG_MIFARE_1K              = 0x02,
    112       TAG_MIFARE_4K              = 0x03,
    113       TAG_UNKNOWN                = 0xff
    114     } TAG_TYPE_T;
    115 
    116     // Valid authentication keys
    117     typedef enum {
    118       KEY_TYPE_EEPROM_A0         = 0x10,
    119       KEY_TYPE_EEPROM_A1         = 0x11,
    120       KEY_TYPE_EEPROM_A2         = 0x12,
    121       KEY_TYPE_EEPROM_A3         = 0x13,
    122       KEY_TYPE_EEPROM_A4         = 0x14,
    123       KEY_TYPE_EEPROM_A5         = 0x15,
    124       KEY_TYPE_EEPROM_A6         = 0x16,
    125       KEY_TYPE_EEPROM_A7         = 0x17,
    126       KEY_TYPE_EEPROM_A8         = 0x18,
    127       KEY_TYPE_EEPROM_A9         = 0x19,
    128       KEY_TYPE_EEPROM_A10        = 0x1a,
    129       KEY_TYPE_EEPROM_A11        = 0x1b,
    130       KEY_TYPE_EEPROM_A12        = 0x1c,
    131       KEY_TYPE_EEPROM_A13        = 0x1d,
    132       KEY_TYPE_EEPROM_A14        = 0x1e,
    133       KEY_TYPE_EEPROM_A15        = 0x1f,
    134 
    135       KEY_TYPE_EEPROM_B0         = 0x20,
    136       KEY_TYPE_EEPROM_B1         = 0x21,
    137       KEY_TYPE_EEPROM_B2         = 0x22,
    138       KEY_TYPE_EEPROM_B3         = 0x23,
    139       KEY_TYPE_EEPROM_B4         = 0x24,
    140       KEY_TYPE_EEPROM_B5         = 0x25,
    141       KEY_TYPE_EEPROM_B6         = 0x26,
    142       KEY_TYPE_EEPROM_B7         = 0x27,
    143       KEY_TYPE_EEPROM_B8         = 0x28,
    144       KEY_TYPE_EEPROM_B9         = 0x29,
    145       KEY_TYPE_EEPROM_B10        = 0x2a,
    146       KEY_TYPE_EEPROM_B11        = 0x2b,
    147       KEY_TYPE_EEPROM_B12        = 0x2c,
    148       KEY_TYPE_EEPROM_B13        = 0x2d,
    149       KEY_TYPE_EEPROM_B14        = 0x2e,
    150       KEY_TYPE_EEPROM_B15        = 0x2f,
    151 
    152       KEY_TYPE_A                 = 0xaa,
    153       KEY_TYPE_B                 = 0xbb,
    154 
    155       KEY_TYPE_A_AND_TRANSPORT_F = 0xff
    156     } KEY_TYPES_T;
    157 
    158     /**
    159      * Instantiates an SM130 object
    160      *
    161      * @param uart The UART port.  Default is 0.
    162      * @param reset The Reset pin.  Default is 13.
    163      */
    164     SM130 (int uart=SM130_DEFAULT_UART, int reset=SM130_DEFAULT_RESET_PIN);
    165 
    166     /**
    167      * SM130 object destructor
    168      */
    169     ~SM130 ();
    170 
    171     /**
    172      * Sets the baud rate for the device.  The default is 19200.
    173      *
    174      * @param baud Desired baud rate, default 19200
    175      * @return mraa::Result value
    176      */
    177     mraa::Result setBaudRate(int baud=19200);
    178 
    179     /**
    180      * Gets the firmware version string.
    181      *
    182      * @return The firmware revision
    183      */
    184     std::string getFirmwareVersion();
    185 
    186     /**
    187      * Issues a reset command to the device.
    188      *
    189      * @return true if successful
    190      */
    191     bool reset();
    192 
    193     /**
    194      * Resets the device using the hardware RESET pin.  This is
    195      * required if the device has been put to sleep using the sleep()
    196      * method.
    197      */
    198     void hardwareReset();
    199 
    200     /**
    201      * Checks to see if a tag is in the RF field, and selects it if
    202      * one is present.
    203      *
    204      * @return true if a tag was detected, false if no tag is present
    205      * or an error was detected.
    206      */
    207     bool select();
    208 
    209     /**
    210      * Waits for a tag to enter the RF field for up to 'timeout'
    211      * milliseconds. It will call select() every 100ms until 'timeout'
    212      * has been exceeded.
    213      *
    214      * @param timeout The number of milliseconds to wait for a tag to appear
    215      * @return true if a tag was detected, false if no tag was
    216      * detected within the timeout value, or an error occurred
    217      */
    218     bool waitForTag(uint32_t timeout);
    219 
    220     /**
    221      * Set the authentication key for a block.  Depending on the
    222      * permissions on the tag, the correct key must be authenticated
    223      * for that block in order to perform read and write operations.
    224      *
    225      * @param block The block to authenticate for
    226      * @param keyType one of the KEY_TYPE_T values
    227      * @param key The 6 byte key to use for Type A and Type B keys
    228      * @return true if authentication was successful, false otherwise
    229      */
    230     bool authenticate(uint8_t block, KEY_TYPES_T keyType, std::string key="");
    231 
    232     /**
    233      * Read a 16 byte block.  Depending on the tag, authentication of
    234      * the block may be required for this method to succeed.
    235      *
    236      * @param block The block to read
    237      * @return The 16 byte block if successful, an empty string otherwise
    238      */
    239     std::string readBlock16(uint8_t block);
    240 
    241     /**
    242      * Read a 4 byte value block.  Depending on the tag, authentication of
    243      * the block may be required for this method to succeed.
    244      *
    245      * @param block The block to read
    246      * @return The 4 byte signed integer value block if successful, 0 otherwise
    247      */
    248     int32_t readValueBlock(uint8_t block);
    249 
    250     /**
    251      * Write 16 bytes to a block.  Depending on the tag, authentication of
    252      * the block may be required for this method to succeed.
    253      *
    254      * @param block The block to write
    255      * @param contents A 16 byte string containing the data to write
    256      * @return true if successful, false otherwise
    257      */
    258     bool writeBlock16(uint8_t block, std::string contents);
    259 
    260     /**
    261      * Write to a 4 byte value block.  Depending on the tag,
    262      * authentication of the block may be required for this method to
    263      * succeed.
    264      *
    265      * @param block The block to write
    266      * @param value the signed 4 byte integer to write to the value block
    267      * @return true if successful, false otherwise
    268      */
    269     bool writeValueBlock(uint8_t block, int32_t value);
    270 
    271     /**
    272      * Write 4 bytes to a block.  This is typically used for
    273      * Ultralight tags. Depending on the tag, authentication of the
    274      * block may be required for this method to succeed.
    275      *
    276      * @param block The block to write
    277      * @param contents A 4 byte string containing the data to write
    278      * @return true if successful, false otherwise
    279      */
    280     bool writeBlock4(uint8_t block, std::string contents);
    281 
    282     /**
    283      * Write a key into one of the 16 EEPROM key slots.  This can be a
    284      * Type A or Type B key.  It is not possible to read these keys
    285      * once written.  Once stored, the key can be used for
    286      * authentication without having to send the key itself.  You can
    287      * then use the appropriate KEY_TYPE_EEPROM_* keyTypes in a call
    288      * to authenticate().
    289      *
    290      * @param eepromSector A number between 0 and 15, indicating the
    291      * EEPROM sector you want to store the key in
    292      * @param keyType Either KEY_TYPE_A or KEY_TYPE_B
    293      * @param key The 6 byte key to store in the EEPROM
    294      * @return true if successful, false otherwise
    295      */
    296     bool writeKey(uint8_t eepromSector, KEY_TYPES_T keyType, std::string key);
    297 
    298     /**
    299      * Increment or decrement a value block.
    300      *
    301      * @param block The block to adjust
    302      * @param value The number to increment or decrement the value block by
    303      * @param incr true to increment, false to decrement
    304      * @return The contents of the value block after the operation has
    305      * completed.
    306      */
    307     int32_t adjustValueBlock(uint8_t block, int32_t value, bool incr);
    308 
    309     /**
    310      * Turn the antenna power on or off.  The power is on by default
    311      * after a reset.  If you turn off the antenna, and methods used
    312      * for interacting with tags will fail until power is re-enabled.
    313      *
    314      * @param on true to enable antenna power, false to disable
    315      * @return true if successful, false otherwise
    316      */
    317     bool setAntennaPower(bool on);
    318 
    319     /**
    320      * Read the status of the 2 onboard GPIO input pins.  Bit 0 is for
    321      * input 0, bit 1 for input 1.  All other bits will be 0.
    322      *
    323      * @return bitmask of input port status values
    324      */
    325     uint8_t readPorts();
    326 
    327     /**
    328      * Set the output status of the 2 onboard gpio outputs.  Bit 0 is for
    329      * output 0, bit 1 for output 1.  All other bits will be discarded.
    330      *
    331      * @param val bitmask of output status bits to write
    332      * @return true if successful, false otherwise
    333      */
    334     bool writePorts(uint8_t val);
    335 
    336     /**
    337      * Halts a tag.  Once a tag is halted, it cannot be accessed until
    338      * it is removed and reinserted into the RF field and selected.
    339      *
    340      * @return true if successful, false otherwise
    341      */
    342     bool haltTag();
    343 
    344     /**
    345      * Changes the baud rate of the SM130.  WARNING: This is a
    346      * potentially dangerous command that could cause you to lose
    347      * contact with the device.  Once the command is validated and
    348      * issued, the host baudrate will be changed to match, and this
    349      * method will wait for a response at the new baudrate for up to 1
    350      * second.
    351      *
    352      * If this response does not arrive, the old baudrate will be
    353      * restored, though there is no way to know whether the SM130
    354      * actually succeessfully executed the baudrate change.
    355      *
    356      * Once the SM130 has changed it's baudrate, the new value will be
    357      * stored in it's EEPROM, and any further access to the device
    358      * will need to use the new baudrate.  This is true even after a
    359      * power on reset.
    360      *
    361      * @param baud The new baud rate to set.  Valid values are 9600,
    362      * 19200, 38400, 57600, and 115200.
    363      * @return true if successful, false otherwise
    364      */
    365     bool setSM130BaudRate(int baud);
    366 
    367     /**
    368      * Put the SM130 to sleep.  Once the device has been put to sleep,
    369      * the only way to wake it is via hardwareReset() or a power
    370      * cycle.
    371      *
    372      * @return true if successful, false otherwise
    373      */
    374     bool sleep();
    375 
    376     /**
    377      * Get the last error that occurred.  After a successful
    378      * operation, this will be 0. See the datasheet for the various
    379      * errors that can occur in various circumstances.
    380      *
    381      * @return The last error code, or 0 if the last operation succeeded.
    382      */
    383     char getLastErrorCode() { return m_lastErrorCode; };
    384 
    385     /**
    386      * Get the text representation of the last error that occurred.
    387      * The returned string is empty if the last operation completed
    388      * successfully.
    389      *
    390      * @return The last error string if an error occurred, or an empty
    391      * string if the last operation succeeded.
    392      */
    393     std::string getLastErrorString() { return m_lastErrorString; };
    394 
    395     /**
    396      * Get the UID length of the currently selected tag.
    397      *
    398      * @return The UID length of the currently selected tag, or 0 if
    399      * no tag is currently selected.
    400      */
    401     int getUIDLen() { return m_uidLen; };
    402 
    403     /**
    404      * Get the UID of the currently selected tag.
    405      *
    406      * @return The UID of the currently selected tag, or an empty string if
    407      * no tag is currently selected.
    408      */
    409     std::string getUID() { return m_uid; };
    410 
    411     /**
    412      * Get the tag type of the currently selected tag.
    413      *
    414      * @return The tag type of the currently selected tag, or TAG_NONE
    415      * if no tag is currently selected.
    416      */
    417     TAG_TYPE_T getTagType() { return m_tagType; };
    418 
    419     /**
    420      * Convert the supplied tag type into a human readable string.
    421      *
    422      * @param tag One of the TAG_TYPE_T values
    423      * @return A string representation of the supplied tag type
    424      */
    425     std::string tag2String(TAG_TYPE_T tag);
    426 
    427     /**
    428      * This is a convenience function that converts a supplied string
    429      * into a space separated hex formatted string.  This can be
    430      * useful for printing out binary data in a human readable format,
    431      * like the UID.
    432      *
    433      * @param input The string to convert
    434      * @return A string representation of the input in space separated
    435      * hex values
    436      */
    437     std::string string2HexString(std::string input);
    438 
    439   protected:
    440     mraa::Uart m_uart;
    441     mraa::Gpio m_gpioReset;
    442 
    443     std::string sendCommand(CMD_T cmd, std::string data);
    444     void initClock();
    445     uint32_t getMillis();
    446 
    447   private:
    448     int m_uidLen;
    449     std::string m_uid;
    450 
    451     char m_lastErrorCode;
    452     std::string m_lastErrorString;
    453 
    454     TAG_TYPE_T m_tagType;
    455 
    456     int m_baud;
    457 
    458     struct timeval m_startTime;
    459 
    460     void clearError()
    461     {
    462       m_lastErrorCode = 0;
    463       m_lastErrorString.clear();
    464     }
    465   };
    466 
    467 }
    468