pn53x.c

00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library
00003  * 
00004  * Copyright (C) 2009, Roel Verdult
00005  * 
00006  * This program is free software: you can redistribute it and/or modify it
00007  * under the terms of the GNU Lesser General Public License as published by the
00008  * Free Software Foundation, either version 3 of the License, or (at your
00009  * option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00014  * more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 
00025 #ifdef HAVE_CONFIG_H
00026   #include "config.h"
00027 #endif // HAVE_CONFIG_H
00028 
00029 #include <string.h>
00030 #include <stdio.h>
00031 
00032 #include "pn53x.h"
00033 
00034 #include "../bitutils.h"
00035 
00036 // PN53X configuration
00037 const byte_t pncmd_get_firmware_version       [  2] = { 0xD4,0x02 };
00038 const byte_t pncmd_get_general_status         [  2] = { 0xD4,0x04 };
00039 const byte_t pncmd_get_register               [  4] = { 0xD4,0x06 };
00040 const byte_t pncmd_set_register               [  5] = { 0xD4,0x08 };
00041 const byte_t pncmd_set_parameters             [  3] = { 0xD4,0x12 };
00042 const byte_t pncmd_rf_configure               [ 14] = { 0xD4,0x32 };
00043 
00044 // Reader
00045 const byte_t pncmd_initiator_list_passive        [264] = { 0xD4,0x4A };
00046 const byte_t pncmd_initiator_jump_for_dep        [ 68] = { 0xD4,0x56 };
00047 const byte_t pncmd_initiator_select              [  3] = { 0xD4,0x54 };
00048 const byte_t pncmd_initiator_deselect            [  3] = { 0xD4,0x44,0x00 };
00049 const byte_t pncmd_initiator_release             [  3] = { 0xD4,0x52,0x00 };
00050 const byte_t pncmd_initiator_set_baud_rate       [  5] = { 0xD4,0x4E };
00051 const byte_t pncmd_initiator_exchange_data       [265] = { 0xD4,0x40 };
00052 const byte_t pncmd_initiator_exchange_raw_data   [266] = { 0xD4,0x42 };
00053 const byte_t pncmd_initiator_auto_poll           [  5] = { 0xD4,0x60 };
00054 
00055 // Target
00056 const byte_t pncmd_target_get_data            [  2] = { 0xD4,0x86 };
00057 const byte_t pncmd_target_set_data            [264] = { 0xD4,0x8E };
00058 const byte_t pncmd_target_init                [ 39] = { 0xD4,0x8C };
00059 const byte_t pncmd_target_virtual_card        [  4] = { 0xD4,0x14 };
00060 const byte_t pncmd_target_receive             [  2] = { 0xD4,0x88 };
00061 const byte_t pncmd_target_send                [264] = { 0xD4,0x90 };
00062 const byte_t pncmd_target_get_status          [  2] = { 0xD4,0x8A };
00063 
00064 
00065 bool pn53x_transceive(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen)
00066 {
00067   byte_t abtRx[MAX_FRAME_LEN];
00068   size_t szRxLen;
00069 
00070   // Check if receiving buffers are available, if not, replace them
00071   if (!pszRxLen || !pbtRx)
00072   {
00073     pbtRx = abtRx;
00074     pszRxLen = &szRxLen;
00075   }
00076 
00077   *pszRxLen = MAX_FRAME_LEN;
00078   // Call the tranceive callback function of the current device
00079   if (!pnd->pdc->transceive(pnd->nds,pbtTx,szTxLen,pbtRx,pszRxLen)) return false;
00080 
00081   // Make sure there was no failure reported by the PN53X chip (0x00 == OK)
00082   if (pbtRx[0] != 0) return false;
00083 
00084   // Succesful transmission
00085   return true;
00086 }
00087 
00088 byte_t pn53x_get_reg(const nfc_device_t* pnd, uint16_t ui16Reg)
00089 {
00090   uint8_t ui8Value;
00091   size_t szValueLen = 1;
00092   byte_t abtCmd[sizeof(pncmd_get_register)];
00093   memcpy(abtCmd,pncmd_get_register,sizeof(pncmd_get_register));
00094 
00095   abtCmd[2] = ui16Reg >> 8;
00096   abtCmd[3] = ui16Reg & 0xff;
00097   // We can not use pn53x_transceive() because abtRx[0] gives no status info
00098   pnd->pdc->transceive(pnd->nds,abtCmd,4,&ui8Value,&szValueLen);
00099   return ui8Value;
00100 }
00101 
00102 bool pn53x_set_reg(const nfc_device_t* pnd, uint16_t ui16Reg, uint8_t ui8SybmolMask, uint8_t ui8Value)
00103 {
00104   byte_t abtCmd[sizeof(pncmd_set_register)];
00105   memcpy(abtCmd,pncmd_set_register,sizeof(pncmd_set_register));
00106 
00107   abtCmd[2] = ui16Reg >> 8;
00108   abtCmd[3] = ui16Reg & 0xff;
00109   abtCmd[4] = ui8Value | (pn53x_get_reg(pnd,ui16Reg) & (~ui8SybmolMask));
00110   // We can not use pn53x_transceive() because abtRx[0] gives no status info
00111   return pnd->pdc->transceive(pnd->nds,abtCmd,5,NULL,NULL);
00112 }
00113 
00114 bool pn53x_set_parameters(const nfc_device_t* pnd, uint8_t ui8Value)
00115 {
00116   byte_t abtCmd[sizeof(pncmd_set_parameters)];
00117   memcpy(abtCmd,pncmd_set_parameters,sizeof(pncmd_set_parameters));
00118 
00119   abtCmd[2] = ui8Value;
00120   // We can not use pn53x_transceive() because abtRx[0] gives no status info
00121   return pnd->pdc->transceive(pnd->nds,abtCmd,3,NULL,NULL);
00122 }
00123 
00124 bool pn53x_set_tx_bits(const nfc_device_t* pnd, uint8_t ui8Bits)
00125 {
00126   // Test if we need to update the transmission bits register setting
00127   if (pnd->ui8TxBits != ui8Bits)
00128   {
00129     // Set the amount of transmission bits in the PN53X chip register
00130     if (!pn53x_set_reg(pnd,REG_CIU_BIT_FRAMING,SYMBOL_TX_LAST_BITS,ui8Bits)) return false;
00131 
00132     // Store the new setting
00133     ((nfc_device_t*)pnd)->ui8TxBits = ui8Bits;
00134   }
00135   return true;
00136 }
00137 
00138 bool pn53x_wrap_frame(const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtFrame, size_t* pszFrameBits)
00139 {
00140   byte_t btFrame;
00141   byte_t btData;
00142   uint32_t uiBitPos;
00143   uint32_t uiDataPos = 0;
00144   size_t szBitsLeft = szTxBits;
00145 
00146   // Make sure we should frame at least something
00147   if (szBitsLeft == 0) return false;
00148 
00149   // Handle a short response (1byte) as a special case
00150   if (szBitsLeft < 9)
00151   {
00152     *pbtFrame = *pbtTx;
00153     *pszFrameBits = szTxBits;
00154     return true;
00155   }
00156 
00157   // We start by calculating the frame length in bits
00158   *pszFrameBits = szTxBits + (szTxBits/8);
00159 
00160   // Parse the data bytes and add the parity bits
00161   // This is really a sensitive process, mirror the frame bytes and append parity bits
00162   // buffer = mirror(frame-byte) + parity + mirror(frame-byte) + parity + ...
00163     // split "buffer" up in segments of 8 bits again and mirror them
00164   // air-bytes = mirror(buffer-byte) + mirror(buffer-byte) + mirror(buffer-byte) + ..
00165   while(true)
00166   {
00167     // Reset the temporary frame byte;
00168     btFrame = 0;
00169 
00170     for (uiBitPos=0; uiBitPos<8; uiBitPos++)
00171     {
00172       // Copy as much data that fits in the frame byte
00173       btData = mirror(pbtTx[uiDataPos]);
00174       btFrame |= (btData >> uiBitPos);
00175       // Save this frame byte
00176       *pbtFrame = mirror(btFrame);
00177       // Set the remaining bits of the date in the new frame byte and append the parity bit
00178       btFrame = (btData << (8-uiBitPos));
00179       btFrame |= ((pbtTxPar[uiDataPos] & 0x01) << (7-uiBitPos));
00180       // Backup the frame bits we have so far
00181       pbtFrame++;
00182       *pbtFrame = mirror(btFrame);
00183       // Increase the data (without parity bit) position
00184       uiDataPos++;
00185       // Test if we are done
00186       if (szBitsLeft < 9) return true;
00187       szBitsLeft -= 8;
00188     }
00189     // Every 8 data bytes we lose one frame byte to the parities
00190     pbtFrame++;
00191   }
00192 }
00193 
00194 bool pn53x_unwrap_frame(const byte_t* pbtFrame, const size_t szFrameBits, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar)
00195 {
00196   byte_t btFrame;
00197   byte_t btData;
00198   uint8_t uiBitPos;
00199   uint32_t uiDataPos = 0;
00200   byte_t* pbtFramePos = (byte_t*) pbtFrame;
00201   size_t szBitsLeft = szFrameBits;
00202 
00203   // Make sure we should frame at least something
00204   if (szBitsLeft == 0) return false;
00205 
00206   // Handle a short response (1byte) as a special case
00207   if (szBitsLeft < 9)
00208   {
00209     *pbtRx = *pbtFrame;
00210     *pszRxBits = szFrameBits;
00211     return true;
00212   }
00213 
00214   // Calculate the data length in bits
00215   *pszRxBits = szFrameBits - (szFrameBits/9);
00216 
00217   // Parse the frame bytes, remove the parity bits and store them in the parity array
00218   // This process is the reverse of WrapFrame(), look there for more info
00219   while(true)
00220   {
00221     for (uiBitPos=0; uiBitPos<8; uiBitPos++)
00222     {
00223       btFrame = mirror(pbtFramePos[uiDataPos]);
00224       btData = (btFrame << uiBitPos);
00225       btFrame = mirror(pbtFramePos[uiDataPos+1]);
00226       btData |= (btFrame >> (8-uiBitPos));
00227       pbtRx[uiDataPos] = mirror(btData);
00228       if(pbtRxPar != NULL) pbtRxPar[uiDataPos] = ((btFrame >> (7-uiBitPos)) & 0x01);
00229       // Increase the data (without parity bit) position
00230       uiDataPos++;
00231       // Test if we are done
00232       if (szBitsLeft < 9) return true;
00233       szBitsLeft -= 9;
00234     }
00235     // Every 8 data bytes we lose one frame byte to the parities
00236     pbtFramePos++;
00237   }
00238 }
00239