| /* |
| * Author: Jon Trulson <jtrulson@ics.com> |
| * Copyright (c) 2015 Intel Corporation. |
| * |
| * 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> |
| #include <iostream> |
| |
| #include <stdlib.h> |
| #include <stdint.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/time.h> |
| #include <sys/select.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| |
| #include <mraa/common.hpp> |
| #include <mraa/uart.hpp> |
| #include <mraa/gpio.hpp> |
| |
| #define SM130_DEFAULT_UART 0 |
| #define SM130_DEFAULT_RESET_PIN 13 |
| |
| namespace upm { |
| |
| /** |
| * @brief SM130 RFID Reader Module library |
| * @defgroup sm130 libupm-sm130 |
| * @ingroup sparkfun uart gpio rfid |
| */ |
| |
| /** |
| * @library sm130 |
| * @sensor sm130 |
| * @comname SM130 RFID Reader |
| * @type rfid |
| * @man sparkfun |
| * @web https://www.sparkfun.com/products/10126 |
| * @con uart gpio |
| * |
| * @brief API for the SM130 RFID Reader Module |
| * |
| * This module defines the SM130 interface for the sm130 RFID library |
| * |
| * This module was developed using an SM130 and a Sparkfun RFID |
| * Evaluation shield using a UART for communications. It should be |
| * fairly trivial to add support for I2C communication in the |
| * future, if you have the correct firmware on the SM130. |
| * |
| * @image html sm130.jpg |
| * <br><em>SM130 RFID Reader image provided by SparkFun* under |
| * <a href=https://creativecommons.org/licenses/by-nc-sa/3.0/> |
| * CC BY-NC-SA-3.0</a>.</em> |
| * |
| * @snippet sm130.cxx Interesting |
| */ |
| |
| class SM130 { |
| |
| public: |
| |
| // Valid commands |
| typedef enum { |
| CMD_RESET = 0x80, |
| CMD_VERSION = 0x81, |
| CMD_SEEK_TAG = 0x82, |
| CMD_SELECT_TAG = 0x83, |
| CMD_AUTHENTICATE = 0x85, |
| CMD_READ16 = 0x86, |
| CMD_READ_VALUE = 0x87, |
| CMD_WRITE16 = 0x89, |
| CMD_WRITE_VALUE = 0x8a, |
| CMD_WRITE4 = 0x8b, |
| CMD_WRITE_KEY = 0x8c, |
| CMD_INC_VALUE = 0x8d, |
| CMD_DEC_VALUE = 0x8e, |
| CMD_ANTENNA_POWER = 0x90, |
| CMD_READ_PORT = 0x91, |
| CMD_WRITE_PORT = 0x92, |
| CMD_HALT_TAG = 0x93, |
| CMD_SET_BAUD = 0x94, |
| CMD_SLEEP = 0x96 |
| } CMD_T; |
| |
| // valid tag types. |
| typedef enum { |
| TAG_NONE = 0x00, // error/invalid |
| |
| TAG_MIFARE_ULTRALIGHT = 0x01, |
| TAG_MIFARE_1K = 0x02, |
| TAG_MIFARE_4K = 0x03, |
| TAG_UNKNOWN = 0xff |
| } TAG_TYPE_T; |
| |
| // Valid authentication keys |
| typedef enum { |
| KEY_TYPE_EEPROM_A0 = 0x10, |
| KEY_TYPE_EEPROM_A1 = 0x11, |
| KEY_TYPE_EEPROM_A2 = 0x12, |
| KEY_TYPE_EEPROM_A3 = 0x13, |
| KEY_TYPE_EEPROM_A4 = 0x14, |
| KEY_TYPE_EEPROM_A5 = 0x15, |
| KEY_TYPE_EEPROM_A6 = 0x16, |
| KEY_TYPE_EEPROM_A7 = 0x17, |
| KEY_TYPE_EEPROM_A8 = 0x18, |
| KEY_TYPE_EEPROM_A9 = 0x19, |
| KEY_TYPE_EEPROM_A10 = 0x1a, |
| KEY_TYPE_EEPROM_A11 = 0x1b, |
| KEY_TYPE_EEPROM_A12 = 0x1c, |
| KEY_TYPE_EEPROM_A13 = 0x1d, |
| KEY_TYPE_EEPROM_A14 = 0x1e, |
| KEY_TYPE_EEPROM_A15 = 0x1f, |
| |
| KEY_TYPE_EEPROM_B0 = 0x20, |
| KEY_TYPE_EEPROM_B1 = 0x21, |
| KEY_TYPE_EEPROM_B2 = 0x22, |
| KEY_TYPE_EEPROM_B3 = 0x23, |
| KEY_TYPE_EEPROM_B4 = 0x24, |
| KEY_TYPE_EEPROM_B5 = 0x25, |
| KEY_TYPE_EEPROM_B6 = 0x26, |
| KEY_TYPE_EEPROM_B7 = 0x27, |
| KEY_TYPE_EEPROM_B8 = 0x28, |
| KEY_TYPE_EEPROM_B9 = 0x29, |
| KEY_TYPE_EEPROM_B10 = 0x2a, |
| KEY_TYPE_EEPROM_B11 = 0x2b, |
| KEY_TYPE_EEPROM_B12 = 0x2c, |
| KEY_TYPE_EEPROM_B13 = 0x2d, |
| KEY_TYPE_EEPROM_B14 = 0x2e, |
| KEY_TYPE_EEPROM_B15 = 0x2f, |
| |
| KEY_TYPE_A = 0xaa, |
| KEY_TYPE_B = 0xbb, |
| |
| KEY_TYPE_A_AND_TRANSPORT_F = 0xff |
| } KEY_TYPES_T; |
| |
| /** |
| * Instantiates an SM130 object |
| * |
| * @param uart The UART port. Default is 0. |
| * @param reset The Reset pin. Default is 13. |
| */ |
| SM130 (int uart=SM130_DEFAULT_UART, int reset=SM130_DEFAULT_RESET_PIN); |
| |
| /** |
| * SM130 object destructor |
| */ |
| ~SM130 (); |
| |
| /** |
| * Sets the baud rate for the device. The default is 19200. |
| * |
| * @param baud Desired baud rate, default 19200 |
| * @return mraa::Result value |
| */ |
| mraa::Result setBaudRate(int baud=19200); |
| |
| /** |
| * Gets the firmware version string. |
| * |
| * @return The firmware revision |
| */ |
| std::string getFirmwareVersion(); |
| |
| /** |
| * Issues a reset command to the device. |
| * |
| * @return true if successful |
| */ |
| bool reset(); |
| |
| /** |
| * Resets the device using the hardware RESET pin. This is |
| * required if the device has been put to sleep using the sleep() |
| * method. |
| */ |
| void hardwareReset(); |
| |
| /** |
| * Checks to see if a tag is in the RF field, and selects it if |
| * one is present. |
| * |
| * @return true if a tag was detected, false if no tag is present |
| * or an error was detected. |
| */ |
| bool select(); |
| |
| /** |
| * Waits for a tag to enter the RF field for up to 'timeout' |
| * milliseconds. It will call select() every 100ms until 'timeout' |
| * has been exceeded. |
| * |
| * @param timeout The number of milliseconds to wait for a tag to appear |
| * @return true if a tag was detected, false if no tag was |
| * detected within the timeout value, or an error occurred |
| */ |
| bool waitForTag(uint32_t timeout); |
| |
| /** |
| * Set the authentication key for a block. Depending on the |
| * permissions on the tag, the correct key must be authenticated |
| * for that block in order to perform read and write operations. |
| * |
| * @param block The block to authenticate for |
| * @param keyType one of the KEY_TYPE_T values |
| * @param key The 6 byte key to use for Type A and Type B keys |
| * @return true if authentication was successful, false otherwise |
| */ |
| bool authenticate(uint8_t block, KEY_TYPES_T keyType, std::string key=""); |
| |
| /** |
| * Read a 16 byte block. Depending on the tag, authentication of |
| * the block may be required for this method to succeed. |
| * |
| * @param block The block to read |
| * @return The 16 byte block if successful, an empty string otherwise |
| */ |
| std::string readBlock16(uint8_t block); |
| |
| /** |
| * Read a 4 byte value block. Depending on the tag, authentication of |
| * the block may be required for this method to succeed. |
| * |
| * @param block The block to read |
| * @return The 4 byte signed integer value block if successful, 0 otherwise |
| */ |
| int32_t readValueBlock(uint8_t block); |
| |
| /** |
| * Write 16 bytes to a block. Depending on the tag, authentication of |
| * the block may be required for this method to succeed. |
| * |
| * @param block The block to write |
| * @param contents A 16 byte string containing the data to write |
| * @return true if successful, false otherwise |
| */ |
| bool writeBlock16(uint8_t block, std::string contents); |
| |
| /** |
| * Write to a 4 byte value block. Depending on the tag, |
| * authentication of the block may be required for this method to |
| * succeed. |
| * |
| * @param block The block to write |
| * @param value the signed 4 byte integer to write to the value block |
| * @return true if successful, false otherwise |
| */ |
| bool writeValueBlock(uint8_t block, int32_t value); |
| |
| /** |
| * Write 4 bytes to a block. This is typically used for |
| * Ultralight tags. Depending on the tag, authentication of the |
| * block may be required for this method to succeed. |
| * |
| * @param block The block to write |
| * @param contents A 4 byte string containing the data to write |
| * @return true if successful, false otherwise |
| */ |
| bool writeBlock4(uint8_t block, std::string contents); |
| |
| /** |
| * Write a key into one of the 16 EEPROM key slots. This can be a |
| * Type A or Type B key. It is not possible to read these keys |
| * once written. Once stored, the key can be used for |
| * authentication without having to send the key itself. You can |
| * then use the appropriate KEY_TYPE_EEPROM_* keyTypes in a call |
| * to authenticate(). |
| * |
| * @param eepromSector A number between 0 and 15, indicating the |
| * EEPROM sector you want to store the key in |
| * @param keyType Either KEY_TYPE_A or KEY_TYPE_B |
| * @param key The 6 byte key to store in the EEPROM |
| * @return true if successful, false otherwise |
| */ |
| bool writeKey(uint8_t eepromSector, KEY_TYPES_T keyType, std::string key); |
| |
| /** |
| * Increment or decrement a value block. |
| * |
| * @param block The block to adjust |
| * @param value The number to increment or decrement the value block by |
| * @param incr true to increment, false to decrement |
| * @return The contents of the value block after the operation has |
| * completed. |
| */ |
| int32_t adjustValueBlock(uint8_t block, int32_t value, bool incr); |
| |
| /** |
| * Turn the antenna power on or off. The power is on by default |
| * after a reset. If you turn off the antenna, and methods used |
| * for interacting with tags will fail until power is re-enabled. |
| * |
| * @param on true to enable antenna power, false to disable |
| * @return true if successful, false otherwise |
| */ |
| bool setAntennaPower(bool on); |
| |
| /** |
| * Read the status of the 2 onboard GPIO input pins. Bit 0 is for |
| * input 0, bit 1 for input 1. All other bits will be 0. |
| * |
| * @return bitmask of input port status values |
| */ |
| uint8_t readPorts(); |
| |
| /** |
| * Set the output status of the 2 onboard gpio outputs. Bit 0 is for |
| * output 0, bit 1 for output 1. All other bits will be discarded. |
| * |
| * @param val bitmask of output status bits to write |
| * @return true if successful, false otherwise |
| */ |
| bool writePorts(uint8_t val); |
| |
| /** |
| * Halts a tag. Once a tag is halted, it cannot be accessed until |
| * it is removed and reinserted into the RF field and selected. |
| * |
| * @return true if successful, false otherwise |
| */ |
| bool haltTag(); |
| |
| /** |
| * Changes the baud rate of the SM130. WARNING: This is a |
| * potentially dangerous command that could cause you to lose |
| * contact with the device. Once the command is validated and |
| * issued, the host baudrate will be changed to match, and this |
| * method will wait for a response at the new baudrate for up to 1 |
| * second. |
| * |
| * If this response does not arrive, the old baudrate will be |
| * restored, though there is no way to know whether the SM130 |
| * actually succeessfully executed the baudrate change. |
| * |
| * Once the SM130 has changed it's baudrate, the new value will be |
| * stored in it's EEPROM, and any further access to the device |
| * will need to use the new baudrate. This is true even after a |
| * power on reset. |
| * |
| * @param baud The new baud rate to set. Valid values are 9600, |
| * 19200, 38400, 57600, and 115200. |
| * @return true if successful, false otherwise |
| */ |
| bool setSM130BaudRate(int baud); |
| |
| /** |
| * Put the SM130 to sleep. Once the device has been put to sleep, |
| * the only way to wake it is via hardwareReset() or a power |
| * cycle. |
| * |
| * @return true if successful, false otherwise |
| */ |
| bool sleep(); |
| |
| /** |
| * Get the last error that occurred. After a successful |
| * operation, this will be 0. See the datasheet for the various |
| * errors that can occur in various circumstances. |
| * |
| * @return The last error code, or 0 if the last operation succeeded. |
| */ |
| char getLastErrorCode() { return m_lastErrorCode; }; |
| |
| /** |
| * Get the text representation of the last error that occurred. |
| * The returned string is empty if the last operation completed |
| * successfully. |
| * |
| * @return The last error string if an error occurred, or an empty |
| * string if the last operation succeeded. |
| */ |
| std::string getLastErrorString() { return m_lastErrorString; }; |
| |
| /** |
| * Get the UID length of the currently selected tag. |
| * |
| * @return The UID length of the currently selected tag, or 0 if |
| * no tag is currently selected. |
| */ |
| int getUIDLen() { return m_uidLen; }; |
| |
| /** |
| * Get the UID of the currently selected tag. |
| * |
| * @return The UID of the currently selected tag, or an empty string if |
| * no tag is currently selected. |
| */ |
| std::string getUID() { return m_uid; }; |
| |
| /** |
| * Get the tag type of the currently selected tag. |
| * |
| * @return The tag type of the currently selected tag, or TAG_NONE |
| * if no tag is currently selected. |
| */ |
| TAG_TYPE_T getTagType() { return m_tagType; }; |
| |
| /** |
| * Convert the supplied tag type into a human readable string. |
| * |
| * @param tag One of the TAG_TYPE_T values |
| * @return A string representation of the supplied tag type |
| */ |
| std::string tag2String(TAG_TYPE_T tag); |
| |
| /** |
| * This is a convenience function that converts a supplied string |
| * into a space separated hex formatted string. This can be |
| * useful for printing out binary data in a human readable format, |
| * like the UID. |
| * |
| * @param input The string to convert |
| * @return A string representation of the input in space separated |
| * hex values |
| */ |
| std::string string2HexString(std::string input); |
| |
| protected: |
| mraa::Uart m_uart; |
| mraa::Gpio m_gpioReset; |
| |
| std::string sendCommand(CMD_T cmd, std::string data); |
| void initClock(); |
| uint32_t getMillis(); |
| |
| private: |
| int m_uidLen; |
| std::string m_uid; |
| |
| char m_lastErrorCode; |
| std::string m_lastErrorString; |
| |
| TAG_TYPE_T m_tagType; |
| |
| int m_baud; |
| |
| struct timeval m_startTime; |
| |
| void clearError() |
| { |
| m_lastErrorCode = 0; |
| m_lastErrorString.clear(); |
| } |
| }; |
| |
| } |