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