/** * @brief this function emits a REQB command to a PICC device * @param *pDataRead : Pointer to the response * @retval ISO14443B_SUCCESSCODE : the function is successful. * @retval ISO14443B_ERRORCODE_DEFAULT : an error occured */ int8_t ISO14443B_ReqB ( uint8_t *pDataRead ) { int8_t status; uc8 ReqB[] = { /* APf */ ISO14443B_ANTICOLLISION_PREFIX_BYTE , /* AFI */ ISO14443B_AFI_ALL_FAMILIES , /* Parameters */ ISO14443B_EXTENDED_ATQB_NOT_SUPPORTED | ISO14443B_REQB_ATTEMPT | ISO14443B_SLOT_MARKER_1 }; /* sends the command to the PCD device*/ errchk(PCD_SendRecv(0x03,ReqB,pDataRead)); /* Filling of the data structure */ ISO14443B_Card.IsDetected = true; /* complete the ISO 14443 type B strucure */ ISO14443B_CompleteStruture (pDataRead); return ISO14443B_SUCCESSCODE; Error: return ISO14443B_ERRORCODE_DEFAULT; }
/** * @brief this functions sends the HLTA command to the PCD device * @param *pDataRead : Pointer to the PCD response * @return ISO14443A_SUCCESSCODE the function is succesful * @return ISO14443A_ERRORCODE_DEFAULT : an error occured */ static int8_t ISO14443A_HLTA( uint8_t *pDataRead ) { uc8 pdata[]= { 0x50, 0x00, 0x28}; /* send the command to the PCD device*/ PCD_SendRecv(0x03,pdata,pDataRead); return ISO14443A_SUCCESSCODE; }
/** * @brief this function carries out the second level of the anticollision * @param *pDataRead : Pointer to the PCD response * @return ISO14443A_SUCCESSCODE the function is succesful * @return ISO14443A_ERRORCODE_DEFAULT : an error occured */ static int8_t ISO14443A_ACLevel2( uint8_t *pDataRead ) { uint8_t *pDataToSend = &(u95HFBuffer[PCD_DATA_OFFSET]), Length = 0, BccByte ; int8_t status; /* Perform anti-collision */ errchk(ISO14443A_AC(pDataRead, SEL_CASCADE_LVL_2)); //errchk(PCD_SendRecv(0x03,AnnticolParameter,pDataRead)); /* Copies the UID into the data structure */ if(ISO14443A_Card.UIDsize == ISO14443A_UID_DOUBLE_SIZE) { memcpy(&ISO14443A_Card.UID[ISO14443A_UID_PART], &pDataRead[PCD_DATA_OFFSET], ISO14443A_UID_SINGLE_SIZE); } else { memcpy(&ISO14443A_Card.UID[ISO14443A_UID_PART], &pDataRead[PCD_DATA_OFFSET+1], ISO14443A_UID_PART); } /* copies the BCC byte of the card response*/ BccByte = pDataRead[PCD_DATA_OFFSET + ISO14443A_UID_SINGLE_SIZE ]; /* Preparing the buffer who contains the SELECT command */ pDataToSend[Length ++] = SEL_CASCADE_LVL_2; pDataToSend[Length ++] = ISO14443A_NVM_70; /* Copies the UID into the data structure */ if(ISO14443A_Card.UIDsize == ISO14443A_UID_DOUBLE_SIZE) { memcpy(&(pDataToSend[Length]),&(ISO14443A_Card.UID[ISO14443A_UID_PART]) , ISO14443A_UID_SINGLE_SIZE); Length += ISO14443A_UID_SINGLE_SIZE ; } else { pDataToSend[Length ++] = 0x88; memcpy(&(pDataToSend[Length]),&(ISO14443A_Card.UID[ISO14443A_UID_PART]) , ISO14443A_UID_PART); Length += ISO14443A_UID_PART ; } pDataToSend[Length ++] = BccByte; /* Add the control byte : Append the CRC + 8 bits in first byte (standard frame)*/ pDataToSend[Length ++] = PCD_ISO14443A_APPENDCRC | PCD_ISO14443A_A8BITSINFIRSTBYTE; /* emit the select command */ errchk(PCD_SendRecv(Length,pDataToSend,pDataRead)); /* Recovering SAK byte */ ISO14443A_Card.SAK = pDataRead[PCD_DATA_OFFSET]; return ISO14443A_SUCCESSCODE; Error: return ISO14443A_ERRORCODE_DEFAULT; }
/** * @brief this function checks if a card is still in the field * @retval ISO14443B_SUCCESSCODE : the function is successful. * @retval ISO14443B_ERRORCODE_DEFAULT : an error occured */ int8_t ISO14443B_IsCardIntheField ( void ) { uint8_t *pDataRead = u95HFBuffer; uc8 Parameter = 0xB2; int8_t status; /* sends the command to the PCD device*/ errchk(PCD_SendRecv(0x01,&Parameter,pDataRead)); return ISO14443B_SUCCESSCODE; Error: return ISO14443B_ERRORCODE_DEFAULT; }
/** * @brief Handles the WAKE_UP command * @param *pDataRead : Pointer to the response * @return ISO14443A_SUCCESSCODE the function is succesful * @return ISO14443A_ERRORCODE_DEFAULT : an error occured */ static int8_t ISO14443A_PPS( uint8_t *pDataRead ) { uc8 pdata[]= { 0xD0, 0x11, 0x00, 0x28}; int8_t status; /* sends the command to the PCD device*/ errchk(PCD_SendRecv(0x04,pdata,pDataRead)); /* checks the CRC */ errchk(PCD_IsCRCOk (PCD_PROTOCOL_ISO14443A,pDataRead) ); return ISO14443A_SUCCESSCODE; Error: return ISO14443A_ERRORCODE_DEFAULT; }
/** * @brief this functions sends the REQA command to the PCD device * @param *pDataRead : Pointer to the PCD response * @return ISO14443A_SUCCESSCODE the function is succesful * @return ISO14443A_ERRORCODE_DEFAULT : an error occured */ static int8_t ISO14443A_REQA( uint8_t *pDataRead ) { uc8 ReqA[] = { 0x26, 0x07}; int8_t status; /* sends the command to the PCD device*/ errchk(PCD_SendRecv(0x02,ReqA,pDataRead)); /* retrieves the ATQA response */ memcpy(ISO14443A_Card.ATQA, &pDataRead[PCD_DATA_OFFSET], ISO14443A_ATQA_SIZE); /* completes the strucure according to the ATQA response */ ISO14443A_CompleteStructure ( ISO14443A_Card.ATQA ); return ISO14443A_SUCCESSCODE; Error: return ISO14443A_ERRORCODE_DEFAULT; }
/** * @brief this functions emits the RATS command to PICC device * @param *pDataRead : Pointer to the response * @return ISO14443A_SUCCESSCODE the function is succesful * @return ISO14443A_ERRORCODE_DEFAULT : an error occured */ static int8_t ISO14443A_RATS( uint8_t *pDataRead ) { int8_t status; uint8_t FSCI; uc8 pdata[]= { 0xE0, 0x80, 0x28}; /* send the command to the PCD device*/ errchk(PCD_SendRecv(0x03,pdata,pDataRead)); /* check the status byte of the PCD device */ errchk(PCD_IsReaderResultCodeOk (SEND_RECEIVE,pDataRead) ); /* check the CRC */ errchk(PCD_IsCRCOk (PCD_PROTOCOL_ISO14443A,pDataRead) ); FSCI = pDataRead[3]&0x0F; FSC = FSCIToFSC(FSCI); return ISO14443A_SUCCESSCODE; Error: return ISO14443A_ERRORCODE_DEFAULT; }
/** * @brief this function complete the ISO14443B structure according to the AttriB response * @param *pDataRead : Pointer to the PCD response * @retval ISO14443B_SUCCESSCODE : the function is successful. * @retval ISO14443B_ERRORCODE_DEFAULT : an error occured */ int8_t ISO14443B_AttriB( uint8_t *pDataRead ) { int8_t status; uint8_t AttriB[ISO14443B_ATQB_SIZE] = { /* Start byte */ ATTRIB_FIRST_BYTE , /* PUPI */ 0x00 , /* PUPI */ 0x00 , /* PUPI */ 0x00 , /* PUPI */ 0x00 , /* Parameter 1 */ TR0_64_FS | TR1_64_FS | EOF_REQUIRED | SOF_REQUIRED , /* Parameter 2 */ MAX_FRAME_SIZE_256_BYTES | PCD_TO_PICC_106K | PICC_TO_PCD_106K , /* Parameter 3 */ TR2_32_FS | PICC_COMPLIANT_ISO14443_4 , /* Parameter 4 */ CID_0 }; /* copies the PUPI field */ memcpy(&AttriB[1], ISO14443B_Card.PUPI, ISO14443B_MAX_PUPI_SIZE); /* sends the command to the PCD device*/ errchk(PCD_SendRecv(0x09,AttriB,pDataRead)); /* checks the CRC */ errchk(PCD_IsCRCOk (PCD_PROTOCOL_ISO14443B,pDataRead) ); return ISO14443B_SUCCESSCODE; Error: return ISO14443B_ERRORCODE_DEFAULT; }
/** * @brief This functions manage the anticollision * @param *pDataRead : Pointer to the PCD response * @param CascadeLevel : information on the current cascade level * @return ISO14443A_SUCCESSCODE the function is succesful * @return ISO14443A_ERRORCODE_DEFAULT : an error occured */ static int8_t ISO14443A_AC( uint8_t *pDataRead, u8 CascadeLevel ) { u8 AnticolParameter [7] = {0x00, ISO14443A_NVM_20, 0x08,0x00,0x00,0x00,0x00}; u8 NbResponseByte = 0; u8 NbResponseByteOrigin = 0; u8 Collision = 0; u8 ByteCollisionIndex = 0; u8 BitCollisionIndex = 0; u8 RemainingBit = 0; u8 NewByteCollisionIndex = 0; u8 NewBitCollisionIndex = 0; u8 UID[4] = {0x00,0x00,0x00,0x00}; int8_t status; /* prepare command regarding cascade level on-going */ AnticolParameter[0] = CascadeLevel; /* sends the command to the PCD device*/ errchk(PCD_SendRecv(0x03,AnticolParameter,pDataRead)); NbResponseByte = pDataRead[1]; NbResponseByteOrigin = NbResponseByte; Collision = (pDataRead[NbResponseByte-1] & 0x80); ByteCollisionIndex = pDataRead[NbResponseByte]; BitCollisionIndex = pDataRead[NbResponseByte+1]; /* case that should not happend, as occurs because we have miss another collision */ if( BitCollisionIndex == 8) { return ISO14443A_ERRORCODE_DEFAULT; } /* check for collision (Tag of different UID length at the same time not managed so far) */ while( Collision == 0x80) { /* clear collision detection */ Collision = 0x00; /* send the command to the PCD device*/ AnticolParameter[1] = ISO14443A_NVM_20 + ((ByteCollisionIndex) <<4) + (BitCollisionIndex+1); if( ByteCollisionIndex == 0) { AnticolParameter[2] = pDataRead[2] & ((u8)(~(0xFF<<(BitCollisionIndex+1)))); /* ISO said it's better to put collision bit to value 1 */ AnticolParameter[3] = (BitCollisionIndex+1) | 0x40; /* add split frame bit */ UID [0] = AnticolParameter[2]; } else if( ByteCollisionIndex == 1) { AnticolParameter[2] = pDataRead[2]; AnticolParameter[3] = pDataRead[3] & ((u8)(~(0xFF<<(BitCollisionIndex+1)))); /* ISO said it's better to put collision bit to value 1 */ AnticolParameter[4] = (BitCollisionIndex+1) | 0x40; /* add split frame bit */ UID [0] = AnticolParameter[2]; UID [1] = AnticolParameter[3]; } else if( ByteCollisionIndex == 2) { AnticolParameter[2] = pDataRead[2]; AnticolParameter[3] = pDataRead[3]; AnticolParameter[4] = pDataRead[4] & ((u8)(~(0xFF<<(BitCollisionIndex+1)))); /* ISO said it's better to put collision bit to value 1 */ AnticolParameter[5] = (BitCollisionIndex+1) | 0x40; /* add split frame bit */; UID [0] = AnticolParameter[2]; UID [1] = AnticolParameter[3]; UID [2] = AnticolParameter[4]; } else if( ByteCollisionIndex == 3) { AnticolParameter[2] = pDataRead[2]; AnticolParameter[3] = pDataRead[3]; AnticolParameter[4] = pDataRead[4]; AnticolParameter[5] = pDataRead[5] & ((u8)(~(0xFF<<(BitCollisionIndex+1)))); /* ISO said it's better to put collision bit to value 1 */ AnticolParameter[6] = (BitCollisionIndex+1) | 0x40; /* add split frame bit */; UID [0] = AnticolParameter[2]; UID [1] = AnticolParameter[3]; UID [2] = AnticolParameter[4]; UID [3] = AnticolParameter[5]; } else return ISO14443A_ERRORCODE_DEFAULT; /* send part of the UID */ PCD_SendRecv((0x03+ByteCollisionIndex+1),AnticolParameter,pDataRead); if(pDataRead[0] != 0x80) return ISO14443A_ERRORCODE_DEFAULT; /* check if there is another collision to take into account*/ NbResponseByte = pDataRead[1]; Collision = (pDataRead[NbResponseByte-1]) & 0x80; if ( Collision == 0x80) { NewByteCollisionIndex = pDataRead[NbResponseByte]; NewBitCollisionIndex = pDataRead[NbResponseByte+1]; } /* we can check that non-alignement is the one expected */ RemainingBit = 8 - (0x0F & (pDataRead[2+(NbResponseByte-2)-1])); if( RemainingBit == BitCollisionIndex+1) { /* recreate the good UID */ if( ByteCollisionIndex == 0) { UID [0] = ((~(0xFF << (BitCollisionIndex+1))) & AnticolParameter[2]) | pDataRead[2] ; UID [1] = pDataRead[3]; UID [2] = pDataRead[4]; UID [3] = pDataRead[5]; } else if( ByteCollisionIndex == 1) { UID [1] = ((~(0xFF << (BitCollisionIndex+1))) & AnticolParameter[3]) | pDataRead[2] ; UID [2] = pDataRead[3]; UID [3] = pDataRead[4]; } else if( ByteCollisionIndex == 2) { UID [2] = ((~(0xFF << (BitCollisionIndex+1))) & AnticolParameter[4]) | pDataRead[2] ; UID [3] = pDataRead[3]; } else if( ByteCollisionIndex == 3) { UID [3] = ((~(0xFF << (BitCollisionIndex+1))) & AnticolParameter[5]) | pDataRead[2] ; } else return ISO14443A_ERRORCODE_DEFAULT; } else return ISO14443A_ERRORCODE_DEFAULT; /* prepare the buffer expected by the caller */ pDataRead[0] = 0x80; pDataRead[1] = NbResponseByteOrigin; pDataRead[2] = UID [0]; pDataRead[3] = UID [1]; pDataRead[4] = UID [2]; pDataRead[5] = UID [3]; pDataRead[6] = UID[0]^UID[1]^UID[2]^UID[3]; /* if collision was detected restart anticol */ if ( Collision == 0x80) { if( ByteCollisionIndex != NewByteCollisionIndex ) { ByteCollisionIndex += NewByteCollisionIndex; BitCollisionIndex = NewBitCollisionIndex; } else { ByteCollisionIndex += NewByteCollisionIndex; BitCollisionIndex += (NewBitCollisionIndex+1); } } } return ISO14443A_SUCCESSCODE; Error: return ISO14443A_ERRORCODE_DEFAULT; }