diff --git a/NfcEmul/nfcemulator.c b/NfcEmul/nfcemulator.c index ec474e4..956c88c 100644 --- a/NfcEmul/nfcemulator.c +++ b/NfcEmul/nfcemulator.c @@ -1,396 +1,401 @@ -/***************************************************************************** -Written and Copyright (C) by Nicolas Kruse - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*****************************************************************************/ - -#include -#include -#include "nfcemulator.h" - -static uint8_t RX_MASK[18] = {0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32, 0, 64, 0, 128, 0, 0}; -static uint8_t TX_MASK[8] = {1, 2, 4, 8, 16, 32, 64, 128}; -static uint16_t FDT_DELAY[2] = {FDT_DELAY_BIT0, FDT_DELAY_BIT1}; - -static uint8_t REQA[1] = {0x26}; -static uint8_t WUPA[1] = {0x52}; -static uint8_t HLTA[4] = {0x50, 0x00, 0x57, 0}; //'50' '00' CRC_A -static uint8_t ATQA[2] = {0x44, 0x00}; //Anticollision with udi size = double -static uint8_t SEL_CL1[2] = {0x93, 0x20}; -static uint8_t SEL_CL2[2] = {0x95, 0x20}; -static uint8_t CT_UID1[5] = {0x88, 0x04, 0xE3, 0xEF, 0}; //uid0 uid1 uid2 uid3 BCC -static uint8_t UID2[5] = {0xA2, 0xEF, 0x20, 0x80, 0}; //uid3 uid4 uid5 uid6 BCC -static uint8_t SAK_NC[3] = {0x04, 0xDA, 0x17}; //Select acknowledge uid not complete -static uint8_t SAK_C[3] = {0x00, 0xFE, 0x51}; //Select acknowledge uid complete, Type 2 (PICC not compliant to ISO/IEC 14443-4) -static uint8_t READ[1] = {0x30}; -static uint8_t WRITE[1] = {0xA2}; - -uint8_t *sto; //Pointer to tag content -uint16_t stoSize; //Number of avalible bytes on the tag - -uint8_t buffer[64]; -uint8_t rCount = 0; - -void setupNfcEmulator(uint8_t *storage, uint16_t storageSize) -{ - //clock divider for 8 bit timer0: clk/1 -> 13.5225 MHz - TCCR0B |= (1<> 8)^((uint16_t)ch << 8)^((uint16_t)ch<<3)^((uint16_t)ch>>4); - } while (--Length); - - *Data = (uint8_t) (wCrc & 0xFF); - Data++; - *Data = (uint8_t) ((wCrc >> 8) & 0xFF); -} - - -void addBcc(uint8_t *Data) //add exclusive-OR of 4 bytes -{ - Data[4] = Data[0] ^ Data[1] ^ Data[2] ^ Data[3]; -} - -void waitForBitend() -{ - while(!(TIFR1 & (1< 7) - { - if (parity) - { - waitForOneBitTime(); - DDRB &= ~(1<<2); - waitForOneBitTime(); - DDRB |= (1<<2); - } - else - { - waitForOneBitTime(); - DDRB |= (1<<2); - waitForOneBitTime(); - DDRB &= ~(1<<2); - } - - txBytePos++; - txbitPos=0; - parity = 0; - } - } - while(txBytePos < length); - - //Send EOC - waitForOneBitTime(); - DDRB &= ~(1<<2); -} - -inline void resetRxFlags() -{ - TCNT1 = 0; - TIFR1 |= (1< CMIN)) - { - t = TCNT1; - resetRxFlags(); - - hbitPos += (t > CLCS) + (t > CLCM); - - if(hbitPos > 17) - { - bytePos++; - hbitPos -= 18; - buffer[bytePos] = 0; - } - - buffer[bytePos] |= RX_MASK[hbitPos]; - - hbitPos += 2; - } //34 or 41 (hbitPos > 17) click cycles - } - while(~TIFR1 & (1< 7) bytePos++; - - return bytePos; -} - -void sendData(uint8_t block) -{ - uint8_t i = 0; - uint16_t pos = (uint16_t)block * 4; - - for(i=0; i < 16; i++) - { - if (pos >= stoSize) - { - buffer[i] = 0; - } - else - { - buffer[i] = sto[pos]; - } - - pos++; - } - - addCrc16(buffer, 16); - txManchester(buffer, 18); -} - -void receiveData(uint8_t block) -{ - uint8_t i = 0; - uint16_t pos = (uint16_t)block * 4; - uint8_t crc1 = buffer[6]; - uint8_t crc2 = buffer[7]; - - addCrc16(buffer, 6); - - if (buffer[6] == crc1 && buffer[7] == crc2) - { - for(i=2; i < 6; i++) //byte 2-5 contains Data - { - if (pos < stoSize) sto[pos] = buffer[i]; - pos++; - } - - buffer[0] = 0x0A; //ACK - txManchester(buffer, 1); - } - else - { - buffer[0] = 0x01; //NAK for CRC error - txManchester(buffer, 1); - } -} - -void checkForNfcReader() -{ - uint8_t bytes = 1; - uint8_t state = 0; - uint8_t cdow = 8; - - if (ACSR & (1< 0) - { - bytes = rxMiller(); - - if ((state & 7) == S_READY) - { - if (buffer[0] == SEL_CL1[0] && buffer[1] == SEL_CL1[1] ) - { - txManchester(CT_UID1, sizeof(CT_UID1)); - } - else if (buffer[0] == SEL_CL2[0] && buffer[1] == SEL_CL2[1] ) - { - txManchester(UID2, sizeof(UID2)); - } - else if (buffer[0] == SEL_CL1[0] && buffer[1] == 0x70 ) - { - txManchester(SAK_NC, sizeof(SAK_NC)); - } - else if (buffer[0] == SEL_CL2[0] && buffer[1] == 0x70 ) - { - txManchester(SAK_C, sizeof(SAK_C)); - state++; //Set state to ACTIVE - } - else - { - state &= 8; //Set state to IDLE/HALT - } - } - else if ((state & 7) == S_ACTIVE) - { - if (buffer[0] == READ[0]) - { - sendData(buffer[1]); - } - else if (buffer[0] == WRITE[0]) - { - receiveData(buffer[1]); - } - else if (buffer[0] == HLTA[0] && buffer[2] == HLTA[2] ) - { - state = S_HALT; - } - else if(bytes) - { - state &= 8; //Set state to IDLE/HALT - } - } - else if (bytes == 1 && (buffer[0] == REQA[0] || buffer[0] == WUPA[0])) //state == S_IDLE - { - txManchester(ATQA, sizeof(ATQA)); - state = (state & 8) + S_READY; //Set state to READY - } - - cdow -= (bytes == 0); - } - AIN1_PRNG |= (1< +#include +#include "nfcemulator.h" + +static uint8_t RX_MASK[18] = {0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32, 0, 64, 0, 128, 0, 0}; +static uint8_t TX_MASK[8] = {1, 2, 4, 8, 16, 32, 64, 128}; +static uint16_t FDT_DELAY[2] = {FDT_DELAY_BIT0, FDT_DELAY_BIT1}; + +static uint8_t REQA[1] = {0x26}; +static uint8_t WUPA[1] = {0x52}; +static uint8_t HLTA[4] = {0x50, 0x00, 0x57, 0}; //'50' '00' CRC_A +static uint8_t ATQA[2] = {0x44, 0x00}; //Anticollision with udi size = double +static uint8_t SEL_CL1[2] = {0x93, 0x20}; +static uint8_t SEL_CL2[2] = {0x95, 0x20}; +static uint8_t CT_UID1[5] = {0x88, 0x04, 0xE3, 0xEF, 0}; //uid0 uid1 uid2 uid3 BCC +static uint8_t UID2[5] = {0xA2, 0xEF, 0x20, 0x80, 0}; //uid3 uid4 uid5 uid6 BCC +static uint8_t SAK_NC[3] = {0x04, 0xDA, 0x17}; //Select acknowledge uid not complete +static uint8_t SAK_C[3] = {0x00, 0xFE, 0x51}; //Select acknowledge uid complete, Type 2 (PICC not compliant to ISO/IEC 14443-4) +static uint8_t READ[1] = {0x30}; +static uint8_t WRITE[1] = {0xA2}; + +uint8_t *sto; //Pointer to tag content +uint16_t stoSize; //Number of avalible bytes on the tag + +uint8_t buffer[64]; +uint8_t rCount = 0; + +void setupNfcEmulator(uint8_t *storage, uint16_t storageSize) +{ + //clock divider for 8 bit timer0: clk/1 -> 13.5225 MHz + TCCR0B |= (1<> 8)^((uint16_t)ch << 8)^((uint16_t)ch<<3)^((uint16_t)ch>>4); + } while (--Length); + + *Data = (uint8_t) (wCrc & 0xFF); + Data++; + *Data = (uint8_t) ((wCrc >> 8) & 0xFF); +} + + +void addBcc(uint8_t *Data) //add exclusive-OR of 4 bytes +{ + Data[4] = Data[0] ^ Data[1] ^ Data[2] ^ Data[3]; +} + +void waitForBitend() +{ + while(!(TIFR1 & (1< 7) + { + if (parity) + { + waitForOneBitTime(); + DDRB &= ~(1<<2); + waitForOneBitTime(); + DDRB |= (1<<2); + } + else + { + waitForOneBitTime(); + DDRB |= (1<<2); + waitForOneBitTime(); + DDRB &= ~(1<<2); + } + + txBytePos++; + txbitPos=0; + parity = 0; + } + } + while(txBytePos < length); + + //Send EOC + waitForOneBitTime(); + DDRB &= ~(1<<2); +} + +inline void resetRxFlags() +{ + TCNT1 = 0; + TIFR1 |= (1< 16000000) + uint16_t t; //For hi cpu clock a 8 bit variable will overflow (CLCM > 0xFF) + #else + uint8_t t; //For low cpu clock computing time is to low for 16bit a variable + #endif + + uint16_t cDown = 0x0FFF; + uint8_t bytePos = 0; + uint8_t hbitPos = 0; + + OCR1A = CLCL-1; + buffer[0] = 0; + + //Wait for transmission end if there is data arriving + do + { + if (ACSR & (1< 1)) + { + t = TCNT1; + resetRxFlags(); + + hbitPos += (t > CLCS) + (t > CLCM); + + if(hbitPos > 17) + { + bytePos++; + hbitPos -= 18; + buffer[bytePos] = 0; + } + + buffer[bytePos] |= RX_MASK[hbitPos]; + + hbitPos += 2; + } //34 or 41 (hbitPos > 17) click cycles + } + while(~TIFR1 & (1< 7) bytePos++; + + return bytePos; +} + +void sendData(uint8_t block) +{ + uint8_t i = 0; + uint16_t pos = (uint16_t)block * 4; + + for(i=0; i < 16; i++) + { + if (pos >= stoSize) + { + buffer[i] = 0; + } + else + { + buffer[i] = sto[pos]; + } + + pos++; + } + + addCrc16(buffer, 16); + txManchester(buffer, 18); +} + +void receiveData(uint8_t block) +{ + uint8_t i = 0; + uint16_t pos = (uint16_t)block * 4; + uint8_t crc1 = buffer[6]; + uint8_t crc2 = buffer[7]; + + addCrc16(buffer, 6); + + if (buffer[6] == crc1 && buffer[7] == crc2) + { + for(i=2; i < 6; i++) //byte 2-5 contains Data + { + if (pos < stoSize) sto[pos] = buffer[i]; + pos++; + } + + buffer[0] = 0x0A; //ACK + txManchester(buffer, 1); + } + else + { + buffer[0] = 0x01; //NAK for CRC error + txManchester(buffer, 1); + } +} + +void checkForNfcReader() +{ + uint8_t bytes = 1; + uint8_t state = 0; + uint8_t cdow = 8; + + if (ACSR & (1< 0) + { + bytes = rxMiller(); + + if ((state & 7) == S_READY) + { + if (buffer[0] == SEL_CL1[0] && buffer[1] == SEL_CL1[1] ) + { + txManchester(CT_UID1, sizeof(CT_UID1)); + } + else if (buffer[0] == SEL_CL2[0] && buffer[1] == SEL_CL2[1] ) + { + txManchester(UID2, sizeof(UID2)); + } + else if (buffer[0] == SEL_CL1[0] && buffer[1] == 0x70 ) + { + txManchester(SAK_NC, sizeof(SAK_NC)); + } + else if (buffer[0] == SEL_CL2[0] && buffer[1] == 0x70 ) + { + txManchester(SAK_C, sizeof(SAK_C)); + state++; //Set state to ACTIVE + } + else + { + state &= 8; //Set state to IDLE/HALT + } + } + else if ((state & 7) == S_ACTIVE) + { + if (buffer[0] == READ[0]) + { + sendData(buffer[1]); + } + else if (buffer[0] == WRITE[0]) + { + receiveData(buffer[1]); + } + else if (buffer[0] == HLTA[0] && buffer[2] == HLTA[2] ) + { + state = S_HALT; + } + else if(bytes) + { + state &= 8; //Set state to IDLE/HALT + } + } + else if (bytes == 1 && (buffer[0] == REQA[0] || buffer[0] == WUPA[0])) //state == S_IDLE + { + txManchester(ATQA, sizeof(ATQA)); + state = (state & 8) + S_READY; //Set state to READY + } + + cdow -= (bytes == 0); + } + AIN1_PORT |= (1<