mifare.c

00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library examples
00003  * 
00004  * Copyright (C) 2009, Roel Verdult
00005  * Copyright (C) 2010, Romuald Conty, Romain Tartière
00006  * 
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *  1) Redistributions of source code must retain the above copyright notice,
00010  *  this list of conditions and the following disclaimer. 
00011  *  2 )Redistributions in binary form must reproduce the above copyright
00012  *  notice, this list of conditions and the following disclaimer in the
00013  *  documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025  * POSSIBILITY OF SUCH DAMAGE.
00026  * 
00027  * Note that this license only applies on the examples, NFC library itself is under LGPL
00028  *
00029  */
00030 
00031 #include "mifare.h"
00032 
00033 #include <string.h>
00034 
00035 #include <nfc/nfc.h>
00036 
00050 bool
00051 nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp)
00052 {
00053   byte_t  abtRx[265];
00054   size_t  szRx;
00055   size_t  szParamLen;
00056   byte_t  abtCmd[265];
00057   bool    bEasyFraming;
00058 
00059   // Make sure we are dealing with a active device
00060   if (!pnd->bActive)
00061     return false;
00062 
00063   abtCmd[0] = mc;               // The MIFARE Classic command
00064   abtCmd[1] = ui8Block;         // The block address (1K=0x00..0x39, 4K=0x00..0xff)
00065 
00066   switch (mc) {
00067     // Read and store command have no parameter
00068   case MC_READ:
00069   case MC_STORE:
00070     szParamLen = 0;
00071     break;
00072 
00073     // Authenticate command
00074   case MC_AUTH_A:
00075   case MC_AUTH_B:
00076     szParamLen = sizeof (mifare_param_auth);
00077     break;
00078 
00079     // Data command
00080   case MC_WRITE:
00081     szParamLen = sizeof (mifare_param_data);
00082     break;
00083 
00084     // Value command
00085   case MC_DECREMENT:
00086   case MC_INCREMENT:
00087   case MC_TRANSFER:
00088     szParamLen = sizeof (mifare_param_value);
00089     break;
00090 
00091     // Please fix your code, you never should reach this statement
00092   default:
00093     return false;
00094     break;
00095   }
00096 
00097   // When available, copy the parameter bytes
00098   if (szParamLen)
00099     memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen);
00100 
00101   bEasyFraming = pnd->bEasyFraming;
00102   if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) {
00103     nfc_perror (pnd, "nfc_configure");
00104     return false;
00105   }
00106   // Fire the mifare command
00107   if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx)) {
00108     if (pnd->iLastError == EINVRXFRAM) {
00109       // "Invalid received frame" AKA EINVRXFRAM,  usual means we are
00110       // authenticated on a sector but the requested MIFARE cmd (read, write)
00111       // is not permitted by current acces bytes;
00112       // So there is nothing to do here.
00113     } else {
00114       nfc_perror (pnd, "nfc_initiator_transceive_bytes");
00115     }
00116     nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming);
00117     return false;
00118   }
00119   if (!nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming)) {
00120     nfc_perror (pnd, "nfc_configure");
00121     return false;
00122   }
00123 
00124   // When we have executed a read command, copy the received bytes into the param
00125   if (mc == MC_READ) {
00126     if (szRx == 16) {
00127       memcpy (pmp->mpd.abtData, abtRx, 16);
00128     } else {
00129       return false;
00130     }
00131   }
00132   // Command succesfully executed
00133   return true;
00134 }