Basic Read and Writer implementation for an OEM Mifare RWD Device.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RWDMifare.h Source File

RWDMifare.h

00001 /*
00002 Copyright (c) 2010 ARM Limited
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010 
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013 
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020 THE SOFTWARE.
00021 */
00022 
00023 /*
00024 This is a specific and quick implementation for the Mifare MicroRWD modules.
00025 The class configures the reader for Mifare operation and can poll for UIDs.
00026 */
00027 
00028 /* Code originally as above. Only contained set up and ability to read UIDs
00029  * Code was expanded massively to implement read and writing of card blocks by seblovett.
00030  * 
00031  *  Responsibility for bricking any cards if section trailers are written to are entirely 
00032  *  on the user. This code has been written to avoid any chance of bricking the device, and 
00033  *  any attempt to write to section trailers requires effort on the user.
00034  *  
00035  *  Known Bugs and Limitations:
00036  *   - Primitive UI
00037  *
00038  *
00039  *  To Do: 
00040  *   - Turn into USB Device to work with Desktop software, giving a better UI to read and write cards.
00041  *   - Inherit an InterruptIn to trigger a UID read on card detect
00042  */
00043 
00044 
00045 #ifndef RWD_MIFARE_H
00046 #define RWD_MIFARE_H
00047 
00048 #include "mbed.h"
00049 #include "RWDModule.h"
00050 /** \class RWDMifare
00051  *  Used to interface to a OEM-Mifare RFID card reader/writer
00052  */
00053 class RWDMifare : public RWDModule
00054 {
00055 public:
00056     RWDMifare(PinName tx, PinName rx, PinName cts);
00057     virtual ~RWDMifare();
00058     
00059     
00060     /** Error Codes: 
00061      *  An enumerate of the possible error codes generated by the class
00062      */
00063     enum RWDMifareErr 
00064     {
00065         MIFARE_OK, /**< No error */
00066         MIFARE_HW, /**< Hardware-specific error */
00067         MIFARE_NOCARD, /**<  No card in field */
00068         MIFARE_WRONGKEY, /**< Key is not valid (for auth command) */
00069         MIFARE_TRAIL /**< Attempted a write to a section trailer - not allowed */
00070     };
00071     /** Commands: 
00072      *  An enumerate of the commands supported by this class
00073      */
00074     enum MifareCMD 
00075     {
00076         CMD_Get_Status = 0x53,/**<Get Status*/
00077         CMD_Prog_EEPROM = 0x50,/**<Program the internal EEPROM*/
00078         CMD_Read_Block  = 0x52,/**<Read a Block of Data*/
00079         CMD_Write_Block = 0x57,/**<Write a Block of Data*/
00080         CMD_Store_Key = 0x4b,/**<Store a security key*/
00081         CMD_Get_UID = 0x55/**<Read the UID of a card*/
00082     };
00083     
00084     /** Acknowledge Codes: 
00085      *  An enumerate of the masks of status code fields.
00086      */
00087     enum Ack_Code {    
00088         Ack_Code_EEPROM_ERR = 0x01,
00089         Ack_Code_Card_OK = 0x02,
00090         Ack_Code_RX_OK = 0x04,
00091         Ack_Code_RS232_ERR = 0x08,
00092         Ack_Code_MF_Type = 0x10,
00093         Ack_Code_UL_Type = 0x20,
00094         Ack_Code_MRRFC_Err = 0x40
00095     };
00096 
00097     
00098     
00099     /** EEPROM Address:
00100      *  Address constants for accessing the EEPROM Addresses
00101      */
00102     enum EEPROM_ADDR { 
00103     POLL             =0x00,
00104     Aux_Data_OP      =0x01,
00105     Checksum         =0x02,
00106     Mifare_ICODE     =0x03,
00107     Weigand_Parity   =0x04,
00108     Aux_Block_Addr   =0x05,
00109     Key_Number       =0x06,
00110     Beep_Delay       =0x07,
00111     OP_Source_Data   =0x08,
00112     Aux_Out_ReDir    =0x09,
00113     OP_Fmt           =0x0A,
00114     Byte_Order       =0x0B
00115     };  
00116     /** Poll Times:
00117      *  Available values of the EEPROM location controlling Poll Time
00118      */
00119     enum POLL_TIME {
00120     POLL_4ms      = 0x00,
00121     POLL_8ms      = 0x10,
00122     POLL_16ms     = 0x20,
00123     POLL_32ms     = 0x30,
00124     POLL_65ms     = 0x40,
00125     POLL_132ms    = 0x50,  
00126     POLL_262ms_d  = 0x60,
00127     POLL_524ms    = 0x70,
00128     POLL_1s       = 0x80,
00129     POLL_2s       = 0x90,
00130     POLL_4s       = 0xA0,
00131     POLL_8s       = 0xB0
00132     };
00133     /** Auxilary Data:
00134      *  Values to set the function of OP0 and OP1 
00135      */
00136     enum Aux_Data {
00137     Aux_Data_OP_OFF        =0x00,
00138     Aux_Data_OP_24bit_W    =0x01,
00139     Aux_Data_OP_32bit_W    =0x02,
00140     Aux_Data_OP_Serial_OP0 =0x03
00141     };
00142     
00143     /** Mode:
00144      *  Controls whether the device operates in MIFARE or ICODE mode 
00145      *  (NB only Mifare supported, this is included for completion)
00146      */
00147     enum Mifare_Icode {
00148     MIFARE    =0x00,
00149     ICODE     =0x01
00150     };
00151     /** Weigand Parity:
00152      *  Sets the Weigand Parity if the Weigand option is used
00153      *  NB not implemented
00154      */
00155     enum Weigand_Parity {
00156     None    =0x00,
00157     On      =0x01
00158     };
00159     /** OP Source
00160      *  Sets the data output on OP0
00161      */
00162     enum OP_Source_Data {
00163     OP_Source_Data_UID     =0x00,
00164     OP_Source_Data_Block   =0x01
00165     };
00166     /** Aux Output Redirection
00167      * Sets the output pin for OP0 data
00168      */
00169     enum Aux_Out_ReDir {
00170     OP0  =0x00,
00171     TX   =0x01
00172     };
00173     /** OP Format
00174      * Controls the output format of data on OP
00175      */
00176     enum OP_Fmt {
00177     Hex         =0x00,
00178     ASCII       =0x01
00179     };
00180     /** Aux output order
00181      * Changes the byte order data is sent on the Aux output line
00182      */
00183     enum Byte_Order {
00184     Default     =0x00,
00185     Reversed    =0x01
00186     };
00187     //! Initialises the device
00188     /*! Programs the EEPROM to configure in Mifare Mode
00189      *  \return Error code
00190      *  \sa RWDMifareErr
00191      */
00192     RWDMifareErr init();//initialise the device
00193 
00194     //! Gets UID of card, as well as the length of
00195     /*! Reads and returns the UID and length of UID of a card if in detect
00196      *  \param pUID must be at least 10-bytes long
00197      *  \param pLen will contain the length of the UID
00198      *  \return Error code
00199      *  \sa RWDMifareErr
00200      */
00201     RWDMifareErr getUID(uint8_t* pUID, size_t* pLen); 
00202     
00203     //! Gets the Reader Status
00204     /*! Gets the status of the RFID card reader.
00205      *  \param Status - location will be filled with the status value
00206      *  \sa Ack_Code
00207      */
00208     RWDMifareErr getStatus(uint8_t* Status);
00209     
00210     //! Prints a description of status
00211     /*! Method prints lines giving a brief explanation of the Status bits
00212      * \param Status is the status byte received from getStatus()
00213      *  \sa Ack_Code, getStatus()
00214      */
00215     RWDMifareErr printStatus(uint8_t Status);
00216     
00217     //! Programs the EEPROM
00218     /*! Programs the EEPROM of the Card Reader
00219      *  \param Address to program. Enumerated by EEPROM_ADDR
00220      *  \param Value to write. Documented by Enums, depending on field writing to. Sets the internal value to change reader behaviour
00221      *  \sa EEPROM_ADDR, POLL_TIME, Aux_Data, Mifare_Icode, Weigand_Parity, OP_Source_Data, Aux_Out_ReDir, OP_Fmt, Byte_Order 
00222      */
00223     RWDMifareErr Prog_EEPROM(uint8_t Address, uint8_t Value);
00224     
00225     //! Stores an access key to the internal EEPROM Memory
00226     /*! Writes a key to the internal memory to be used to access secured cards
00227      *  \param KeyNumber is the location the key is stored at and is used to reference the key in other operations
00228      *  \param Key is a 6 byte key to be written
00229      */
00230     RWDMifareErr StoreKey(uint8_t KeyNumber, uint8_t* Key);
00231     
00232     //! Reads a block of data from the card
00233     /*! Reads a 16 byte block of memory from the card
00234      *  \param Addr is the block address (0-63 for 1k cards, 0-255 for 4k cards) to read from.
00235      *  \param Keynumber_Tpye is the combined Key Number and card type of the form 0xTxxKKKKK - T => A = 0; B = 1. K is 5 bit key number
00236      *  \param Data is the location that the block data is stored at. Should be at least 16 bytes in length.
00237      */
00238     RWDMifareErr ReadBlock(uint8_t Addr, uint8_t KeyNumber_Type, uint8_t* Data);
00239     
00240     //! Reads a block of data from the card
00241     /*! Reads a 16 byte block of memory from the card
00242      *  \param Addr is the block address (0-63 for 1k cards, 0-255 for 4k cards) to read from.
00243      *  \param Keynumber Key Number to use to access the card, between 0 and 31. 
00244      *  \param Type is the key type to use. 0 = A, !0 = B.
00245      *  \param Data to store the data read back in. Should be at least 16 bytes in length.
00246      */
00247     RWDMifareErr ReadBlock(uint8_t Addr, uint8_t KeyNumber, uint8_t Type, uint8_t* Data);
00248     
00249     //! Writes a block of data to the card
00250     /*! Writes an entire block of data to the RFID card
00251      *  WILL NOT WRITE TO A SECTION TRAILER. Incorrect writing to trailers can render the card useless. Therefore this method WILL NOT ALLOW writing to these to avoid accidentally bricking the card.
00252      *  Section trailers are located at Blocks 3, 7, 11 ... 63 for the 1k cards and lower part of 4k cards, and also at 15, 31, 47 ... 
00253      *  Writing to these sections is the same protocol, but it is necessary to understand the Section Trailers before attempting to do so.
00254      *  \param Addr is the Block Address of a data field to write to.
00255      *  \param Keynumber Key Number to use to access the card, between 0 and 31. 
00256      *  \param Type is the key type to use. 0 = A, !0 = B.
00257      *  \param Data is the source of the data to be written. Should be at least 16 bytes in length.
00258      */
00259     RWDMifareErr WriteBlock(uint8_t Addr, uint8_t KeyNumber, uint8_t Type, uint8_t* Data);
00260     
00261     //! Authorises all cards for the RWD
00262     /*! The Mifare Reader can contain up to 60 internal UIDs to match to a read UID. 
00263      *  This method will write 0xFFFFFFFF to the first field so that all cards brought into detect will be able to be read from the mbed
00264      */
00265     RWDMifareErr AuthAllCards();
00266 };
00267 
00268 #endif