1 /* 2 * Author: Jon Trulson <jtrulson@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 */ getLastErrorCode()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 */ getLastErrorString()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 */ getUIDLen()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 */ getUID()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 */ getTagType()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 clearError()460 void clearError() 461 { 462 m_lastErrorCode = 0; 463 m_lastErrorString.clear(); 464 } 465 }; 466 467 } 468