MfRc500uC.c
资源名称:Phi.rar [点击查看]
上传用户:liao421
上传日期:2013-06-13
资源大小:35k
文件大小:92k
源码类别:
RFID编程
开发平台:
C/C++
- ///////////////////////////////////////////////////////////////////////////////
- // Copyright (c), Philips Semiconductors Gratkorn
- //
- // (C)PHILIPS Electronics N.V.2000
- // All rights are reserved.
- // Philips reserves the right to make changes without notice at any time.
- // Philips makes no warranty, expressed, implied or statutory, including but
- // not limited to any implied warranty of merchantibility or fitness for any
- //particular purpose, or that the use will not infringe any third party patent,
- // copyright or trademark. Philips must not be liable for any loss or damage
- // arising from its use.
- ///////////////////////////////////////////////////////////////////////////////
- #include <string.h>
- #include <stdio.h>
- #include "RICReg.H"
- #include "MfRc500.h"
- #include "PICCCmdConst.h"
- #include "MfErrNo.h"
- /*
- * Projekt: MF EV X00 Firmware
- *
- * $Workfile:: MfRc500uC.c $
- * $Modtime:: 24.06.02 15:41 $
- * $Author:: Hb $
- * $Revision:: 8 $
- *
- *
- * This library modul is written for a C166 microcontroller derivative.
- * The source can be ported to other platforms very easily.
- * In our case the reader module is
- * connected via memory mapped io at base address 0x100000.
- * The interrupt pin of the reader IC is assumed to be connected to
- * the fast external interrupt pin INT0# (active low) and the reset
- * pin of the reader IC should be connected to a dedicated port pin
- * (Port: P1 Pin: 9).
- * In this configuration, a reset of the reader module is independend
- * from the reset of the microcontroller.
- * All protocoll
- * relevant timing constraints are generated
- * by the internal timer of the reader module.
- *
- * Some explanations to the programming method of this library.
- * There are three kind of functions coded in this module.
- *
- * ---- internal functions, which have no prototypes in a header
- * file. This kind of functions are not intended to be used
- * outside of this file
- * ---- commands, which are intended for the reader module itself
- * ---- commands, which are intended for any tag in the rf field.
- * These commands are send to the reader and the reader module
- * transmitts the data to the rf interface.
- *
- * Commands for the reader and for the tag have the appropriate
- * prefix (PCD for Proximity Coupled Device or reader module
- * PICC for Proximity Integrated Circuit Card or tag)
- * and their protypes are defined in the header file.
- * Certainly, each command for a PICC consists of an instruction to the PCD.
- * Therefore
- * the function PcdSingleResponseCmd is very important for the understanding
- * of the communication.
- *
- * The basic functionality is provided by the interrupt service
- * routine (SingleResponseCmd), which closely works together with the function
- * PcdSingleResponseCmd. All kinds of interrupts are serviced by the
- * same ISR.
- */
- ///////////////////////////////////////////////////////////////////////////////
- // M O D U L V A R I A B L E S
- ///////////////////////////////////////////////////////////////////////////////
- // interrupt vector number for interrupt of the RIC
- // select the appropriate value corresponding to the microcontroller in use
- #define READER_INT // e. g. 0x18
- // disable reader interrupt
- // select the appropriate value corresponding to the microcontroller in use
- #define READER_INT_DISABLE // e. g. EXICON &= ~0x0002
- // enable reader interrupt
- // select the appropriate value corresponding to the microcontroller in use
- #define READER_INT_ENABLE // e. g. EXICON |= 0x0002
- // initialize reset pin and change port direction
- // select the appropriate value corresponding to the microcontroller in use
- #define READER_INIT_RESET // e. g. P6 |= 0x20; DP6 |= 0x20
- // set reset pin
- // select the appropriate value corresponding to the microcontroller in use
- #define READER_RESET // e. g. P6 |= 0x20
- // clear reset pin
- // select the appropriate value corresponding to the microcontroller in use
- #define READER_CLEAR_RESET // e. g. P6 &= ~0x20
- // memory base address corresponding to the previous set address select register
- // select the appropriate value corresponding to the microcontroller in use
- #define MEMORY_BASE_ADDRESS 0x100000
- // the RIC has only 3 address lines - page select is necessary
- #define GetRegPage(addr) (0x80 | (addr>>3))
- /* ISO14443 Support Properties
- * Some of the protokoll functions of ISO14443 needs information about
- * the capability of the reader device, which are provided by this
- * constants.
- */
- //{
- #define TCLFSDSNDMAX 8 ///< max. frame size send
- #define TCLFSDRECMAX 8 ///< max. frame size rcv
- #define TCLDSMAX 3 ///< max. baudrate divider PICC --> PCD
- #define TCLDRMAX 3 ///< max. baudrate divider PCD --> PICC
- #define TCLDSDFLT 0 ///< default baudrate divider PICC --> PCD
- #define TCLDRDFLT 0 ///< default baudrate divider PCD --> PICC
- //}
- /* ISR communication structures
- * All parameters are passed to the ISR via this structure.
- */
- //{
- // struct definition for a communication channel between function and ISR
- typedef struct
- {
- unsigned char cmd; //!< command code
- char status; //!< communication status
- unsigned short nBytesSent; //!< how many bytes already sent
- unsigned short nBytesToSend; //!< how many bytes to send
- unsigned short nBytesReceived;//!< how many bytes received
- unsigned long nBitsReceived; //!< how many bits received
- unsigned char irqSource; //!< which interrupts have occured
- unsigned char collPos; /*!< at which position occured a
- collision*/
- unsigned char errFlags; //!< error flags
- unsigned char saveErrorState;//!< accumulated error flags for
- //!< multiple responses
- unsigned char RxAlignWA; //!< workaround for RxAlign = 7
- unsigned char DisableDF; //!< disable disturbance filter
- } MfCmdInfo;
- // Convinience function for initialising the communication structure.
- #define ResetInfo(info)
- info.cmd = 0;
- info.status = MI_OK;
- info.irqSource = 0;
- info.nBytesSent = 0;
- info.nBytesToSend = 0;
- info.nBytesReceived = 0;
- info.nBitsReceived = 0;
- info.collPos = 0;
- info.errFlags = 0;
- info.saveErrorState = 0;
- info.RxAlignWA = 0;
- info.DisableDF = 0;
- // In order to exchange some values between the ISR and the calling function,
- // a struct is provided.
- volatile MfCmdInfo MInfo;
- // communication info stucture
- static volatile MfCmdInfo *MpIsrInfo = 0;
- // ISR send buffer
- static volatile unsigned char *MpIsrOut = 0;
- // ISR receive buffer
- static volatile unsigned char *MpIsrIn = 0;
- //}
- // storage of the last selected serial number including check byte.
- // For multi level serial numbers, only the first 4 bytes are stored.
- unsigned char MLastSelectedSnr[5];
- // storage buffer for receive and transmit routines
- //{
- #define MEMORY_BUFFER_SIZE 300
- volatile unsigned char MemPool[MEMORY_BUFFER_SIZE];
- volatile unsigned char *MSndBuffer = MemPool; // pointer to the transmit buffer
- volatile unsigned char *MRcvBuffer = MemPool; // pointer to the receive buffer
- //}
- /* Higher Baudrate Control
- * attention: RegDecoderControl is modified in CascAnticoll
- * Because of standard baudrate usage during anticollision, the
- * register can be written. For general purpose usage, only some bits
- * should be set.
- *
- * Please pay attention, that the location of the configuration array is
- * in ROM space, that means that on 16 bit microcontroller the access
- * should be word aligned.
- */
- //{
- typedef struct
- {
- unsigned short SubCarrierPulses; ///< RegRxControl1
- unsigned short RxCoding; ///< RegDecoderControl
- unsigned short RxThreshold; ///< RegRxThreshold
- unsigned short BPSKDemControl; ///< RegBPSKDemControl
- } t_DSCfg;
- typedef struct
- {
- unsigned short CoderRate; ///< RegCoderControl
- unsigned short ModWidth; ///< RegModWidth
- } t_DRCfg;
- const t_DSCfg MDSCfg[4] = {{0x73,0x08,0x88,0x00} // Manchaster 106 kBaud
- ,{0x53,0x09,0x50,0x0C} // BPSK 212 kBaud
- ,{0x33,0x09,0x50,0x0C} // BPSK 424 kBaud
- ,{0x13,0x09,0x50,0x0C}}; // BPSK 848 kBaud
- const t_DRCfg MDRCfg[4] = {{0x19,0x13} // Miller 106 kBaud
- ,{0x11,0x07} // Miller 212 kBaud
- ,{0x09,0x03} // Miller 424 kBaud
- ,{0x01,0x01}}; // Miller 848 kBaud
- // data send baudrate divider PICC --> PCD
- static unsigned char MDSI = TCLDSDFLT;
- // data send baudrate divider PCD --> PICC
- static unsigned char MDRI = TCLDRDFLT;
- //}
- // Write one byte to the reader IC address space
- /*!
- * -o address (IN) reader ic register address
- * -o value (IN) 8 bit value
- * return: none
- *
- * Function for writting one char to the reader module
- *
- * The reader module is connected to a 16 bit demultiplexed bus,
- * therefore the address pin of the reader module is mapped as
- * follows: n
- * uC Reader n
- * A1 A0 n
- * A2 A1 n
- * A3 A2 n
- *
- * In order to get the correct address, the original address need to
- * be multiplied by 2.
- */
- #define WriteRawRC(addr,value) *(gpcRCBaseAddress + addr) = value;
- //! Read one byte from the reader IC address space
- /*!
- * -o address (IN) reader ic register address
- * -o value (IN) 8 bit value
- * return: none
- *
- * Function for reading one char from the reader module
- *
- * The reader module is connected to a 16 bit demultiplexed bus,
- * therefore the address pin of the reader module is mapped as
- * follows: n
- * uC Reader n
- * A1 A0 n
- * A2 A1 n
- * A3 A2 n
- *
- * In order to get the correct address, the original address need to
- * be multiplied by 2.
- */
- #define ReadRawRC(addr) (*(gpcRCBaseAddress + addr))
- //! Open Reader IC Connection
- /*!
- * -o none
- * return: MI_OK
- * other error opening reader ic channel
- *
- * Open and initialize communication channel to the reader module
- */
- char OpenRC(void);
- //! Write one byte to the reader IC address space
- /*!
- * -o address (IN) reader ic register address
- * -o value (IN) 8 bit value
- * return: none
- *
- * This function determines the necessary page address of the
- * reader module and writes the page number to the page
- * register and the value to the specified address.
- */
- void WriteRC(unsigned char Address, unsigned char value);
- //! Write one byte to the reader IC address space
- /*
- * -o address (IN) reader IC register address
- * return: value 8 bit data, read from the reader ic address space
- *
- * This function determines the necessary page address of the
- * reader module and writes the page number to the page
- * register and reads the value from the specified address.
- */
- unsigned char ReadRC(unsigned char Address);
- //! Close reader IC communication channel
- /*!
- * -o none
- * return: none
- *
- * Closing the communication channel to the reader module
- */
- void CloseRC(void);
- // In case of a parallel connection, the address space of the reader module
- // needs to be mapped to the address space of the microcontroller. Therefore
- // a base address is reserved.
- unsigned char * const gpcRCBaseAddress = (unsigned char * const)(MEMORY_BASE_ADDRESS);
- ///////////////////////////////////////////////////////////////////////////////
- // Open Reader Communication
- ///////////////////////////////////////////////////////////////////////////////
- char OpenRC(void)
- {
- signed char status = MI_OK;
- READER_INIT_RESET;
- return status;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Close Reader Communication
- ///////////////////////////////////////////////////////////////////////////////
- void CloseRC(void)
- {
- }
- ///////////////////////////////////////////////////////////////////////////////
- // G E N E R I C W R I T E
- ///////////////////////////////////////////////////////////////////////////////
- void WriteRC(unsigned char Address, unsigned char value)
- {
- WriteRawRC(0x00,GetRegPage(Address)); // select appropriate page
- WriteRawRC(Address,value); // write value at the specified
- // address
- }
- ///////////////////////////////////////////////////////////////////////////////
- // G E N E R I C R E A D
- ///////////////////////////////////////////////////////////////////////////////
- unsigned char ReadRC(unsigned char Address)
- {
- WriteRawRC(0x00,GetRegPage(Address)); // select appropriate page
- return ReadRawRC(Address); // read value at the specified
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Prototypes for local functions
- ///////////////////////////////////////////////////////////////////////////////
- /// Internal Authentication State Switch
- /*!
- * -o auth_mode (IN)
- * enum: selects master key A or master key B
- * - PICC_AUTHENT1A
- * - PICC_AUTHENT1B
- *
- * -o *snr (IN)
- * 4 byte serial number of the card, which should be
- * authenticated
- * -o sector (IN) Range [0..15]
- * specifies the key RAM address
- * from which the keys should be taken
- * return: enum:
- * - MI_OK
- * - CCE
- * - MI_BITCOUNTERR wrong number of bits received
- * - MI_AUTHERR wrong keys for selected card
- * - MI_KEYERR error while loading keys
- *
- *
- * Internal authentication state function.
- */
- char Mf500PiccAuthState(unsigned char auth_mode,// PICC_AUTHENT1A, PICC_AUTHENT1B
- unsigned char *snr, // 4 byte serial number
- unsigned char sector); // 0 <= sector <= 15
- // sector address for authentication
- /// Write Baudrate Divider
- /*!
- * -o none
- * return: MI_OK
- *
- * Write function for baudrate divider and PCD properties
- */
- char Mf500PcdWriteAttrib(void);
- /* ISR Communication Structure
- * Data, which have to be passed between ISR and other functions are
- * colleted within one structure.
- */
- //{
- // ISR for Single Response Commands
- /*
- * -o none
- * return: none
- *
- * This function is a central routine in the communication chain between
- * PCD and PICC.
- */
- //interrupt (READER_INT)
- void SingleResponseIsr(void);
- // Command issuer for Single Response Commands
- /*
- * -o cmd (IN)
- * Command type
- * enum:
- * - PCD_IDLE
- * - PCD_WRITEE2
- * - PCD_READE2
- * - PCD_LOADCONFIG
- * - PCD_LOADKEYE2
- * - PCD_AUTHENT1
- * - PCD_CALCCRC
- * - PCD_AUTHENT2
- * - PCD_RECEIVE
- * - PCD_LOADKEY
- * - PCD_TRANSMIT
- * - PCD_TRANSCEIVE
- *
- * send (IN)
- * byte stream of variable length, which should be send to
- * the PICC, the length of stream has to be specified
- * in the info - structure
- * rcv (OUT)
- * byte stream of variable length, which was received
- * from the PICC. The length can be obtained from the
- * info - structure
- * info (OUT)
- * communication and status structure
- * return: enum:
- * - MI_OK operation without error
- * - MI_NOTAGERR no tag in rf field
- * - MI_ACCESSTIMEOUT RIC is not responding in time
- * - MI_COLLERR collision in during rf data transfer
- * - MI_PARITYERR parity error while receiving data
- * - MI_FRAMINGERR framing error - start bit not valid
- * - MI_OVFLERR FIFO overflow - to many data bytes
- * - MI_CRCERR CRC error of received data
- * - MI_NY_IMPLEMENTED internal error - source not identified
- *
- *
- * This function provides the central interface to the reader module.
- * Depending on the "cmd"-value, all necessary interrupts are enabled
- * and the communication is started. While the processing is done by
- * the reader module, this function waits for its completion.
- *
- * It's notable, that the data in the send byte stream is written
- * to the FIFO of the reader module by the ISR itself. Immediate after
- * enabling the interrupts, the LoAlert interrupt is activated.
- *
- * The ISR writes the data to the FIFO. This function is not directly involved
- * in writing or fetching data from FIFO, all work is done by the
- * corresponding ISR.After command completion, the error status is evaluated and
- * returned to the calling function.
- */
- char PcdSingleResponseCmd(unsigned char cmd,
- volatile unsigned char* send,
- volatile unsigned char* rcv,
- volatile MfCmdInfo *info);
- /// Basic Register definitions
- /*!
- * return: none
- */
- char PcdBasicRegisterConfiguration(void);
- /// Set Reader IC Register Bit
- /*!
- * -o reg (IN)
- * register address
- * -o mask (IN)
- * Bit mask to set
- * return: none
- *
- * This function performs a read - modify - write sequence
- * on the specified register. All bits with a 1 in the mask
- * are set - all other bits keep their original value.
- */
- void SetBitMask(unsigned char reg,unsigned char mask);
- /// Clear Reader IC Register Bit
- /*!
- * -o reg (IN)
- * register address
- * -o mask (IN)
- * Bit mask to clear
- * return: none
- *
- * This function performs a read - modify - write sequence
- * on the specified register. All bits with a 1 in the mask
- * are cleared - all other bits keep their original value.
- */
- void ClearBitMask(unsigned char reg,unsigned char mask);
- /// Flush remaining data from the FIFO
- /*!
- * -o none
- * return: none
- *
- * This function erases all remaining data in the MF RC 500's FIFO .
- * Before writing new data or starting a new command, all remaining data
- * from former commands should be deleted.
- */
- void FlushFIFO(void);
- /// Sleep several milliseconds
- /*
- The implementation of this function depends heavily
- on the microcontroller in use. The measurement need not to be
- very accurate. Only make sure, that the periode is not shorter, than
- the required one.
- */
- void SleepMs(unsigned short ms);
- /// Sleep several microseconds
- /*
- The implementation of this function depends heavily
- on the microcontroller in use. The measurement need not to be
- very accurate. Only make sure, that the periode is not shorter, than
- the required one.
- */
- void SleepUs(unsigned short us);
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E M O D U L E C O N F I G U R A T I O N
- ///////////////////////////////////////////////////////////////////////
- char Mf500PcdConfig(void)
- {
- char status = MI_RESETERR;
- status = PcdReset();
- if (status == MI_OK)
- {
- if ((status = PcdBasicRegisterConfiguration()) == MI_OK);
- {
- Mf500PcdWriteAttrib(); // write current modulation parameters
- PcdRfReset(1); // Rf - reset and enable output driver
- }
- }
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E R E M O T E A N T E N N A
- // Configuration of slave module
- ///////////////////////////////////////////////////////////////////////
- char Mf500ActiveAntennaSlaveConfig(void)
- {
- char status = MI_OK;
- FlushFIFO(); // empty FIFO
- ResetInfo(MInfo);
- MSndBuffer[0] = 0x10; // addr low byte
- MSndBuffer[1] = 0x00; // addr high byte
- MSndBuffer[2] = 0x00; // Page
- MSndBuffer[3] = 0x7B; // RegTxControl modsource 11,InvTx2,Tx2RFEn,TX1RFEn
- MSndBuffer[4] = 0x3F; // RegCwConductance
- MSndBuffer[5] = 0x3F; // RFU13
- MSndBuffer[6] = 0x19; // RFU14
- MSndBuffer[7] = 0x13; // RegModWidth
- MSndBuffer[8] = 0x00; // RFU16
- MSndBuffer[9] = 0x00; // RFU17
- MSndBuffer[10] = 0x00; // Page
- MSndBuffer[11] = 0x73; // RegRxControl1
- MSndBuffer[12] = 0x08; // RegDecoderControl
- MSndBuffer[13] = 0x6c; // RegBitPhase
- MSndBuffer[14] = 0xFF; // RegRxThreshold
- MSndBuffer[15] = 0x00; // RegBPSKDemControl
- MSndBuffer[16] = 0x00; // RegRxControl2
- MSndBuffer[17] = 0x00; // RegClockQControl
- MSndBuffer[18] = 0x00; // Page
- MSndBuffer[19] = 0x06; // RegRxWait
- MSndBuffer[20] = 0x03; // RegChannelRedundancy
- MSndBuffer[21] = 0x63; // RegCRCPresetLSB
- MSndBuffer[22] = 0x63; // RegCRCPresetMSB
- MSndBuffer[23] = 0x0; // RFU25
- MSndBuffer[24] = 0x04; // RegMfOutSelect enable mfout = manchester HT
- MSndBuffer[25] = 0x00; // RFU27
- // PAGE 5 FIFO, Timer and IRQ-Pin Configuration
- MSndBuffer[26] = 0x00; // Page
- MSndBuffer[27] = 0x08; // RegFIFOLevel
- MSndBuffer[28] = 0x07; // RegTimerClock
- MSndBuffer[29] = 0x06; // RegTimerControl
- MSndBuffer[30] = 0x0A; // RegTimerReload
- MSndBuffer[31] = 0x02; // RegIRqPinConfig
- MSndBuffer[32] = 0x00; // RFU
- MSndBuffer[33] = 0x00; // RFU
- MInfo.nBytesToSend = 34;
- status = PcdSingleResponseCmd(PCD_WRITEE2,
- MSndBuffer,
- MRcvBuffer,
- &MInfo); // write e2
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E R E M O T E A N T E N N A
- // Configuration of master module
- ///////////////////////////////////////////////////////////////////////
- char Mf500ActiveAntennaMasterConfig(void)
- {
- char status = MI_OK;
- WriteRC(RegRxControl2,0x42);
- WriteRC(RegTxControl,0x10);
- WriteRC(RegBitPhase,0x11);
- WriteRC(RegMfOutSelect,0x02);
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E R E Q U E S T
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccRequest(unsigned char req_code, // request code ALL = 0x52
- // or IDLE = 0x26
- unsigned char *atq) // answer to request
- {
- return Mf500PiccCommonRequest(req_code,atq);
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E C O M M O N R E Q U E S T
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccCommonRequest(unsigned char req_code,
- unsigned char *atq)
- {
- char status = MI_OK;
- //************* initialize ******************************
- if ((status = Mf500PcdSetDefaultAttrib()) == MI_OK)
- {
- PcdSetTmo(60);
- WriteRC(RegChannelRedundancy,0x03); // RxCRC and TxCRC disable, parity enable
- ClearBitMask(RegControl,0x08); // disable crypto 1 unit
- WriteRC(RegBitFraming,0x07); // set TxLastBits to 7
- ResetInfo(MInfo);
- MSndBuffer[0] = req_code;
- MInfo.nBytesToSend = 1;
- MInfo.DisableDF = 1;
- status = PcdSingleResponseCmd(PCD_TRANSCEIVE,
- MSndBuffer,
- MRcvBuffer,
- &MInfo);
- if ((status == MI_OK) && (MInfo.nBitsReceived != 16)) // 2 bytes expected
- {
- status = MI_BITCOUNTERR;
- }
- if ((status == MI_COLLERR) && (MInfo.nBitsReceived == 16)) //
- status = MI_OK; // all received tag-types are combined to the 16 bit
- // in any case, copy received data to output - for debugging reasons
- if (MInfo.nBytesReceived >= 2)
- {
- memcpy(atq,MRcvBuffer,2);
- }
- else
- {
- if (MInfo.nBytesReceived == 1)
- atq[0] = MRcvBuffer[0];
- else
- atq[0] = 0x00;
- atq[1] = 0x00;
- }
- }
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E A N T I C O L L I S I O N
- // for standard select
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccAnticoll (unsigned char bcnt,
- unsigned char *snr)
- {
- return Mf500PiccCascAnticoll(0x93,bcnt,snr); // first cascade level
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E A N T I C O L L I S I O N
- // for extended serial numbers
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccCascAnticoll (unsigned char select_code,
- unsigned char bcnt,
- unsigned char *snr)
- {
- char status = MI_OK;
- char snr_in[4]; // copy of the input parameter snr
- char nbytes = 0; // how many bytes received
- char nbits = 0; // how many bits received
- char complete = 0; // complete snr recived
- short i = 0;
- char byteOffset = 0;
- unsigned char snr_crc; // check byte calculation
- unsigned char snr_check;
- unsigned char dummyShift1; // dummy byte for snr shift
- unsigned char dummyShift2; // dummy byte for snr shift
- //************* Initialisierung ******************************
- if ((status = Mf500PcdSetDefaultAttrib()) == MI_OK)
- {
- PcdSetTmo(106);
- memcpy(snr_in,snr,4);
- WriteRC(RegDecoderControl,0x28); // ZeroAfterColl aktivieren
- ClearBitMask(RegControl,0x08); // disable crypto 1 unit
- //************** Anticollision Loop ***************************
- complete=0;
- while (!complete && (status == MI_OK) )
- {
- // if there is a communication problem on the RF interface, bcnt
- // could be larger than 32 - folowing loops will be defective.
- if (bcnt > 32)
- {
- status = MI_WRONG_PARAMETER_VALUE;
- continue;
- }
- ResetInfo(MInfo);
- MInfo.cmd = select_code; // pass command flag to ISR
- MInfo.DisableDF = 1;
- WriteRC(RegChannelRedundancy,0x03); // RxCRC and TxCRC disable, parity enable
- nbits = bcnt % 8; // remaining number of bits
- if (nbits)
- {
- WriteRC(RegBitFraming,nbits << 4 | nbits); // TxLastBits/RxAlign auf nb_bi
- nbytes = bcnt / 8 + 1;
- // number of bytes known
- // in order to solve an inconsistancy in the anticollision sequence
- // (will be solved soon), the case of 7 bits has to be treated in a
- // separate way
- if (nbits == 7 )
- {
- MInfo.RxAlignWA = 1;
- MInfo.nBitsReceived = 7; // set flag for 7 bit anticoll, which is evaluated
- // in the ISRnBitsReceived
- WriteRC(RegBitFraming,nbits); // reset RxAlign to zero
- }
- }
- else
- {
- nbytes = bcnt / 8;
- }
- MSndBuffer[0] = select_code;
- MSndBuffer[1] = 0x20 + ((bcnt/8) << 4) + nbits; //number of bytes send
- for (i = 0; i < nbytes; i++) // Sende Buffer beschreiben
- {
- MSndBuffer[i + 2] = snr_in[i];
- }
- MInfo.nBytesToSend = 2 + nbytes;
- status = PcdSingleResponseCmd(PCD_TRANSCEIVE,
- MSndBuffer,
- MRcvBuffer,
- &MInfo);
- // in order to solve an inconsistancy in the anticollision sequence
- // (will be solved soon), the case of 7 bits has to be treated in a
- // separate way
- if (MInfo.RxAlignWA)
- {
- // reorder received bits
- dummyShift1 = 0x00;
- for (i = 0; i < MInfo.nBytesReceived; i++)
- {
- dummyShift2 = MRcvBuffer[i];
- MRcvBuffer[i] = (dummyShift1 >> (i+1)) | (MRcvBuffer[i] << (7-i));
- dummyShift1 = dummyShift2;
- }
- MInfo.nBitsReceived -= MInfo.nBytesReceived; // subtract received parity bits
- // recalculation of collision position
- if ( MInfo.collPos ) MInfo.collPos += 7 - (MInfo.collPos + 6) / 9;
- }
- if ( status == MI_OK || status == MI_COLLERR) // no other occured
- {
- byteOffset = 0;
- if ( nbits != 0 ) // last byte was not complete
- {
- snr_in[nbytes - 1] = snr_in[nbytes - 1] | MRcvBuffer[0];
- byteOffset = 1;
- }
- for ( i =0; i < (4 - nbytes); i++)
- {
- snr_in[nbytes + i] = MRcvBuffer[i + byteOffset];
- }
- // R e s p o n s e P r o c e s s i n g
- if ( MInfo.nBitsReceived != (40 - bcnt) ) // not 5 bytes answered
- {
- status = MI_BITCOUNTERR;
- }
- else
- {
- if (status != MI_COLLERR ) // no error and no collision
- {
- // SerCh check
- snr_crc = snr_in[0] ^ snr_in[1] ^ snr_in[2] ^ snr_in[3];
- snr_check = MRcvBuffer[MInfo.nBytesReceived - 1];
- if (snr_crc != snr_check)
- {
- status = MI_SERNRERR;
- }
- else
- {
- complete = 1;
- }
- }
- else // collision occured
- {
- bcnt = bcnt + MInfo.collPos - nbits;
- status = MI_OK;
- }
- }
- }
- }
- }
- // transfer snr_in to snr - even in case of an error - for
- // debugging reasons
- memcpy(snr,snr_in,4);
- //----------------------Einstellungen aus Initialisierung ruecksetzen
- ClearBitMask(RegDecoderControl,0x20); // ZeroAfterColl disable
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E S E L E C T
- // for std. select
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccSelect(unsigned char *snr,
- unsigned char *sak)
- {
- return Mf500PiccCascSelect(0x93,snr,sak); // first cascade level
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E C A S C A D E D S E L E C T
- // for extended serial number
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccCascSelect(unsigned char select_code,
- unsigned char *snr,
- unsigned char *sak)
- {
- char status = MI_OK;
- if ((status = Mf500PcdSetDefaultAttrib()) == MI_OK)
- {
- PcdSetTmo(106);
- WriteRC(RegChannelRedundancy,0x0F); // RxCRC,TxCRC, Parity enable
- ClearBitMask(RegControl,0x08); // disable crypto 1 unit
- //************* Cmd Sequence **********************************
- ResetInfo(MInfo);
- MSndBuffer[0] = select_code;
- MSndBuffer[1] = 0x70; // number of bytes send
- memcpy(MSndBuffer + 2,snr,4);
- MSndBuffer[6] = MSndBuffer[2]
- ^ MSndBuffer[3]
- ^ MSndBuffer[4]
- ^ MSndBuffer[5];
- MInfo.nBytesToSend = 7;
- MInfo.DisableDF = 1;
- status = PcdSingleResponseCmd(PCD_TRANSCEIVE,
- MSndBuffer,
- MRcvBuffer,
- &MInfo);
- *sak = 0;
- if (status == MI_OK) // no timeout occured
- {
- if (MInfo.nBitsReceived != 8) // last byte is not complete
- {
- status = MI_BITCOUNTERR;
- }
- else
- {
- memcpy(MLastSelectedSnr,snr,4);
- }
- }
- // copy received data in any case - for debugging reasons
- *sak = MRcvBuffer[0];
- }
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E P I C C A C T I V A T I O N S E Q E N C E
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccActivateIdle(unsigned char br,
- unsigned char *atq,
- unsigned char *sak,
- unsigned char *uid,
- unsigned char *uid_len)
- {
- unsigned char cascade_level;
- unsigned char sel_code;
- unsigned char uid_index;
- signed char status;
- unsigned char cmdASEL;
- *uid_len = 0;
- //call activation with def. divs
- status = Mf500PcdSetDefaultAttrib();
- if (status == MI_OK)
- {
- status = Mf500PiccCommonRequest(PICC_REQIDL,atq);
- }
- if (status == MI_OK)
- {
- if((atq[0] & 0x1F) == 0x00) // check lower 5 bits, for tag-type
- // all tags within this 5 bits have to
- // provide a bitwise anticollision
- {
- status = MI_NOBITWISEANTICOLL;
- }
- }
- if (status == MI_OK)
- {
- //Get UID in 1 - 3 levels (standard, [double], [triple] )
- //-------
- switch(br)
- {
- case 0: cmdASEL = PICC_ANTICOLL1; break;
- case 1: cmdASEL = PICC_ANTICOLL11; break;
- case 2: cmdASEL = PICC_ANTICOLL12; break;
- case 3: cmdASEL = PICC_ANTICOLL13; break;
- default:
- status = MI_BAUDRATE_NOT_SUPPORTED; break;
- }
- }
- if (status == MI_OK)
- {
- cascade_level = 0;
- uid_index = 0;
- do
- {
- //Select code depends on cascade level
- sel_code = cmdASEL + (2 * cascade_level);
- cmdASEL = PICC_ANTICOLL1; // reset anticollistion level for calculation
- //ANTICOLLISION
- status = Mf500PiccCascAnticoll(sel_code, 0, &uid[uid_index]);
- //SELECT
- if (status == MI_OK)
- {
- status = Mf500PiccCascSelect(sel_code, &uid[uid_index], sak);
- if (status == MI_OK)
- {
- cascade_level++;
- //we differ cascaded and uncascaded UIDs
- if (*sak & 0x04) // if cascaded, bit 2 is set in answer to select
- {
- //this UID is cascaded, remove the cascaded tag that is
- //0x88 as first of the 4 byte received
- memmove(&uid[uid_index], &uid[uid_index + 1], 3);
- uid_index += 3;
- *uid_len += 3;
- }
- else
- {
- //this UID is not cascaded -> the length is 4 bytes
- uid_index += 4;
- *uid_len += 4;
- }
- }
- }
- }
- while((status == MI_OK) // error status
- && (*sak & 0x04) // no further cascade level
- && (cascade_level < 3)); // highest cascade level is reached
- }
- if (status == MI_OK)
- {
- //Exit function, if cascade level is triple and sak indicates another
- //cascase level.
- if ((cascade_level == 3) && (*sak & 0x04))
- {
- *uid_len = 0;
- status = MI_CASCLEVEX;
- }
- Mf500PcdSetAttrib(br,br);
- }
- return (status);
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E P I C C A C T I V A T I O N S E Q E N C E
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccActivateWakeup(unsigned char br,
- unsigned char *atq,
- unsigned char *sak,
- unsigned char *uid,
- unsigned char uid_len)
- {
- unsigned char cascade_level;
- unsigned char uid_index;
- unsigned char tmpuid[4];
- unsigned char sel_code;
- unsigned char cmdASEL;
- signed char status;
- //call activation with def. divs
- status = Mf500PcdSetDefaultAttrib();
- if (status == MI_OK)
- {
- status = Mf500PiccCommonRequest(PICC_REQALL,atq);
- }
- if (status == MI_OK)
- {
- if ((atq[0] & 0x1F) == 0x00) // check lower 5 bits, for tag-type
- // all tags within this 5 bits have to
- // provide a bitwise anticollision
- {
- status = MI_NOBITWISEANTICOLL;
- }
- }
- if (status == MI_OK)
- {
- //Get UID in 1 - 3 levels (standard, [double], [triple] )
- //-------
- switch(br)
- {
- case 0: cmdASEL = PICC_ANTICOLL1; break;
- case 1: cmdASEL = PICC_ANTICOLL11; break;
- case 2: cmdASEL = PICC_ANTICOLL12; break;
- case 3: cmdASEL = PICC_ANTICOLL13; break;
- default:
- status = MI_BAUDRATE_NOT_SUPPORTED; break;
- }
- }
- if (status == MI_OK)
- {
- //Select UID in up to 3 cascade levels (standard, [double], [triple] )
- //------------------------------------
- cascade_level = 0;
- uid_index = 0;
- tmpuid[0] = 0x88; //first byte of cascaded UIDs is 0x88 (cascaded tag)
- do
- {
- sel_code = cmdASEL + (2 * cascade_level);
- cmdASEL = PICC_ANTICOLL1; // reset anticollistion level for calculation
- //get the next UID part if we need to cascade
- if((uid_len - uid_index) > 4)
- {
- //ok, we need to cascade the UID
- memcpy(&tmpuid[1], &uid[uid_index], 3);
- uid_index += 3;
- }
- else
- {
- //ah, how nice. no need to cascade
- memcpy(tmpuid, &uid[uid_index], 4);
- uid_index += 4;
- }
- status = Mf500PiccCascSelect(sel_code, tmpuid, sak);
- if(status == MI_OK)
- {
- cascade_level++;
- }
- }
- while((status == MI_OK ) // error occured
- && (*sak & 0x04) // no further cascade level
- && ((uid_index + 1) < uid_len) // all bytes of snr sent
- && (cascade_level < 3)); // highest cascade level reached
- }
- if ( status == MI_OK)
- {
- //Exit function, if UID length is not of expected length
- if ((uid_index) != uid_len)
- {
- status = MI_SERNRERR ;
- }
- }
- if (status == MI_OK)
- {
- //Exit function, if cascade level is triple and sak indicates another
- //cascase level.
- if ((cascade_level == 3) && (*sak & 0x04))
- {
- status = MI_SERNRERR;
- }
- }
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // M I F A R E A U T H E N T I C A T I O N
- // calling compatible version
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccAuth(unsigned char key_type, // PICC_AUTHENT1A or PICC_AUTHENT1B
- unsigned char key_addr, // key address in reader storage
- unsigned char block) // block number which should be
- // authenticated
- {
- char status = MI_OK;
- status = Mf500PiccAuthE2( key_type,
- MLastSelectedSnr,
- key_addr,
- block);
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // A U T H E N T I C A T I O N
- // W I T H K E Y S F R O M E 2 P R O M
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccAuthE2( unsigned char auth_mode, // PICC_AUTHENT1A or PICC_AUTHENT1B
- unsigned char *snr, // 4 bytes card serial number
- unsigned char key_sector, // 0 <= key_sector <= 15
- unsigned char block) // 0 <= block <= 256
- {
- char status = MI_OK;
- // eeprom address calculation
- // 0x80 ... offset
- // key_sector ... sector
- // 0x18 ... 2 * 12 = 24 = 0x18
- unsigned short e2addr = 0x80 + key_sector * 0x18;
- unsigned char *e2addrbuf = (unsigned char*)&e2addr;
- PcdSetTmo(106);
- if (auth_mode == PICC_AUTHENT1B)
- e2addr += 12; // key B offset
- FlushFIFO(); // empty FIFO
- ResetInfo(MInfo);
- memcpy(MSndBuffer,e2addrbuf,2); // write low and high byte of address
- MInfo.nBytesToSend = 2;
- // write load command
- if ((status=PcdSingleResponseCmd(PCD_LOADKEYE2,MSndBuffer,MRcvBuffer,&MInfo)) == MI_OK)
- {
- // execute authentication
- status = Mf500PiccAuthState(auth_mode,snr,block);
- }
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // C O D E K E Y S
- ///////////////////////////////////////////////////////////////////////
- char Mf500HostCodeKey( unsigned char *uncoded, // 6 bytes key value uncoded
- unsigned char *coded) // 12 bytes key value coded
- {
- char status = MI_OK;
- unsigned char cnt = 0;
- unsigned char ln = 0; // low nibble
- unsigned char hn = 0; // high nibble
- for (cnt = 0; cnt < 6; cnt++)
- {
- ln = uncoded[cnt] & 0x0F;
- hn = uncoded[cnt] >> 4;
- coded[cnt * 2 + 1] = (~ln << 4) | ln;
- coded[cnt * 2 ] = (~hn << 4) | hn;
- }
- return MI_OK;
- }
- ///////////////////////////////////////////////////////////////////////
- // A U T H E N T I C A T I O N
- // W I T H P R O V I D E D K E Y S
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccAuthKey( unsigned char auth_mode,
- unsigned char *snr,
- unsigned char *keys,
- unsigned char block)
- {
- char status = MI_OK;
- unsigned char i = 0;
- PcdSetTmo(106);
- FlushFIFO(); // empty FIFO
- ResetInfo(MInfo);
- memcpy(MSndBuffer,keys,12); // write 12 bytes of the key
- MInfo.nBytesToSend = 12;
- // write load command
- if ((status=PcdSingleResponseCmd(PCD_LOADKEY,MSndBuffer,MRcvBuffer,&MInfo)) == MI_OK)
- {
- // execute authentication
- status = Mf500PiccAuthState(auth_mode,snr,block);
- }
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // S T O R E K E Y S I N E E P R O M
- ///////////////////////////////////////////////////////////////////////
- char Mf500PcdLoadKeyE2(unsigned char key_type,
- unsigned char sector,
- unsigned char *uncoded_keys)
- {
- // eeprom address calculation
- // 0x80 ... offset
- // key_sector ... sector
- // 0x18 ... 2 * 12 = 24 = 0x18
- signed char status = MI_OK;
- unsigned short e2addr = 0x80 + sector * 0x18;
- unsigned char coded_keys[12];
- if (key_type == PICC_AUTHENT1B)
- e2addr += 12; // key B offset
- if ((status = Mf500HostCodeKey(uncoded_keys,coded_keys)) == MI_OK)
- status = PcdWriteE2( e2addr,12,coded_keys);
- return status;
- }
- ///////////////////////////////////////////////////////////////////////
- // A U T H E N T I C A T I O N S T A T E S
- ///////////////////////////////////////////////////////////////////////
- char Mf500PiccAuthState( unsigned char auth_mode,
- unsigned char *snr,
- unsigned char block)
- {
- char status = MI_OK;
- unsigned char i = 0;
- WriteRC(RegChannelRedundancy,0x07); // RxCRC disable,TxCRC, Parity enable
- PcdSetTmo(150);
- MSndBuffer[0] = auth_mode; // write authentication command
- MSndBuffer[1] = block; // write block number for authentication
- memcpy(MSndBuffer + 2,snr,4); // write 4 bytes card serial number
- ResetInfo(MInfo);
- MInfo.nBytesToSend = 6;
- if ((status = PcdSingleResponseCmd(PCD_AUTHENT1,
- MSndBuffer,
- MRcvBuffer,
- &MInfo)) == MI_OK)
- {
- if (ReadRC(RegSecondaryStatus) & 0x07) // RxLastBits mu