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.cpp Source File

RWDMifare.cpp

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 #include "RWDMifare.h"
00024 
00025 RWDMifare::RWDMifare(PinName tx, PinName rx, PinName cts) : RWDModule(tx, rx, cts)
00026 {
00027 
00028 }
00029 
00030 
00031 RWDMifare::~RWDMifare()
00032 {
00033 
00034 }
00035 RWDMifare::RWDMifareErr RWDMifare::init()
00036 {
00037     const uint8_t config[] = {0x03, 0x00}; //Configure ready for Mifare Op (0x00 to addr 0x03 in EEPROM)
00038     uint8_t resp[64] = {0};
00039     //Cf http://www.ibtechnology.co.uk/pdf/MF_ICprot.pdf
00040     //Command 'P': cf p11
00041     //EEPROM parameters: cf p12
00042     //Ack check: cf p13
00043     command(CMD_Prog_EEPROM, config, 2, resp, 0, 0x80, 0x89); //Program EEPROM command is 0x50 ('P')
00044     while(!ready()) { //Wait for a response
00045 
00046     }
00047 
00048     if(!result()) { //If this fails, there is something wrong with the hardware
00049         return MIFARE_HW;
00050     }
00051 
00052     return MIFARE_OK;
00053 }
00054 RWDMifare::RWDMifareErr RWDMifare::Prog_EEPROM(uint8_t Address, uint8_t Value)
00055 {
00056     const uint8_t config[] = {Address, Value}; //Configure ready for Mifare Op (0x00 to addr 0x03 in EEPROM)
00057     uint8_t resp[64] = {0};
00058     //Cf http://www.ibtechnology.co.uk/pdf/MF_ICprot.pdf
00059     //Command 'P': cf p11
00060     //EEPROM parameters: cf p12
00061     //Ack check: cf p13
00062     command(CMD_Prog_EEPROM, config, 2, resp, 0, 0x80, 0x81); //Program EEPROM command is 0x50 ('P')
00063     while(!ready()) { //Wait for a response
00064 
00065     }
00066 
00067     if(!result()) { //If this fails, there is something wrong with the hardware
00068         return MIFARE_HW;
00069     }
00070 
00071     return MIFARE_OK;
00072 
00073 }
00074 RWDMifare::RWDMifareErr RWDMifare::printStatus(uint8_t Status)
00075 {
00076     printf("\n\rEEPROM Error\t= %d", (Status & Ack_Code_EEPROM_ERR));
00077     printf("\n\rCard Okay \t= %d", (Status & Ack_Code_Card_OK)>>1);
00078     printf("\n\rRX Okay \t= %d", (Status & Ack_Code_RX_OK)>>2);
00079     printf("\n\rRS232 Error \t= %d", (Status & Ack_Code_RS232_ERR)>>3);
00080     printf("\n\rMF Type \t= %d", (Status & Ack_Code_MF_Type)>>4);
00081     printf("\n\rUL Type \t= %d", (Status & Ack_Code_UL_Type)>>5);
00082     printf("\n\rMFRC Error \t= %d", (Status & Ack_Code_MRRFC_Err)>>6);
00083     return MIFARE_OK;
00084 }
00085 RWDMifare::RWDMifareErr RWDMifare::getStatus(uint8_t* Status)
00086 {
00087     //Gets the status code of the Mifare
00088     command(CMD_Get_Status, NULL, 0, Status, 1, 0x86,0x86);
00089     printf("\n\rStatus 0x%02x", *Status);
00090 
00091     return MIFARE_OK;
00092 }
00093 RWDMifare::RWDMifareErr RWDMifare::getUID(uint8_t* pUID, size_t* pLen) //pUID must be at least 10-bytes long
00094 //(A Mifare UID can either be 4, 7, or 10 bytes long)
00095 //This reader does not support 10 bytes uids
00096 {
00097     //Cf http://www.ibtechnology.co.uk/pdf/MF_ICprot.pdf
00098     //Command 'U': cf p19
00099     //Ack check: cf p13
00100     command(CMD_Get_UID, NULL, 0, pUID, 7, 0x86, 0x86); //UID command is 0x55 ('U')
00101     while(!ready()) { //Wait for a response
00102 
00103     }
00104 
00105     if(!result()) { //Error detected, there is no card in field
00106         return MIFARE_NOCARD;
00107     }
00108 
00109     //printf("Got card.\n\r");
00110 
00111     //Checks UID length returned by reader
00112     int i;
00113     for(i = 0; i < 7; i++) {
00114         if(pUID[i] == 0) //End of UID, cf http://www.ibtechnology.co.uk/pdf/MF_ICprot.pdf p19
00115             break;
00116     }
00117     *pLen = i;
00118 
00119     return MIFARE_OK;
00120 }
00121 
00122 RWDMifare::RWDMifareErr RWDMifare::StoreKey(uint8_t KeyNumber, uint8_t* Key)
00123 {
00124     uint8_t cmd[7] = {0};
00125     //command[0] = CMD_Store_Key;
00126     cmd[0] = KeyNumber & 31; //mask it. 
00127     for(int i = 0; i < 6; i++)
00128     {
00129         cmd[i+1] = Key[i];
00130     }
00131 /*    printf("Command:\n");
00132     for(int i = 0; i < 8; i ++){
00133         printf("0x%02x ", command[i]);
00134     }*/
00135     command(CMD_Store_Key, cmd, 7, NULL, 0, 0x80, 0x89);
00136     while(!ready()) { //Wait for a response
00137 
00138     }
00139 
00140     if(!result()) { //Error detected, there is no card in field
00141         return MIFARE_NOCARD;
00142     }
00143 
00144     return MIFARE_OK;
00145 }
00146 RWDMifare::RWDMifareErr RWDMifare::AuthAllCards()
00147 {
00148     if (Prog_EEPROM(0x0C, 0xFF))
00149         return MIFARE_HW;
00150     if (Prog_EEPROM(0x0C, 0xFF))
00151         return MIFARE_HW;
00152     if (Prog_EEPROM(0x0C, 0xFF))
00153         return MIFARE_HW;
00154     if (Prog_EEPROM(0x0C, 0xFF))
00155         return MIFARE_HW;
00156     return MIFARE_OK; 
00157 }
00158 
00159 RWDMifare::RWDMifareErr RWDMifare::ReadBlock(uint8_t Addr, uint8_t KeyNumber_Type, uint8_t* Data)
00160 {
00161     uint8_t cmd[2] = {Addr, KeyNumber_Type};
00162     command(CMD_Read_Block, cmd, 2, Data, 16, 0x96, 0xFE);
00163     while(!ready()) { //Wait for a response
00164 
00165     }
00166 
00167     if(!result()) { //Error detected, there is no card in field
00168         return MIFARE_NOCARD;
00169     }
00170 
00171     return MIFARE_OK;
00172     
00173 }
00174 RWDMifare::RWDMifareErr RWDMifare::ReadBlock(uint8_t Addr, uint8_t KeyNumber, uint8_t Type, uint8_t* Data)
00175 {
00176     KeyNumber &= 0x1F; 
00177     if(Type)
00178         KeyNumber |= 0x80;
00179     return ReadBlock(Addr, KeyNumber, Data);
00180     
00181 }
00182 RWDMifare::RWDMifareErr RWDMifare::WriteBlock(uint8_t Addr, uint8_t KeyNumber, uint8_t Type, uint8_t* Data)
00183 {
00184     //CARE MUST BE TAKEN WHEN WRITING TO A SECTION TRAILER. 
00185     //THIS METHOD WILL NOT WRITE TO A SECTION TRAILER, ONLY USER DATA
00186     if(Addr < 32)
00187     {
00188         if ((Addr & 0x3) == 0x3) // section trailer occurs on blocks 3, 7, 11, 15 . . .
00189             return MIFARE_TRAIL;
00190     }
00191     else //only applicable for 4k cards 
00192     {
00193         if ((Addr & 0xF) == 0xF) //for sectors 32 - 39, trailer occurs in block 15. 
00194             return MIFARE_TRAIL;
00195     }
00196     
00197     //get here, writing to a user field.
00198     KeyNumber &= 0x1F; 
00199     if(Type)
00200         KeyNumber |= 0x80;
00201     
00202     uint8_t cmd[18];
00203     cmd[0] = Addr;
00204     cmd[1] = KeyNumber;
00205     for(int i = 0; i < 16; i ++)
00206     {
00207         cmd[i+2] = Data[i];
00208     }
00209     printf("Command to write:\n");
00210     for(int i = 0; i < 18;i++){
00211         printf("0x%02x ", cmd[i]);
00212     }
00213     printf("\r\n");
00214     command(CMD_Write_Block, cmd, 18, NULL, 0, 0x96, 0xFE);
00215     while(!ready()) { //Wait for a response
00216 
00217     }
00218 
00219     if(!result()) { //Error detected, there is no card in field
00220         return MIFARE_NOCARD;
00221     }
00222     return MIFARE_OK;
00223 }