I build up some kind of RFID-Reader with an Raspberry Pi 3 and an RC522 using this code as a start: https://github.com/mxgxw/MFRC522-python. Unfortunately I'm not able to get a APDU-Response from my card after sending any APDU-Command.
My current workflow is more or less the ISO 14443-4:
- Search for cards
- receive ATQA
- Perform anticollision and select card
- Determine whether card is supporting ISO-14443-4 protocol or not
- Send RATS and receive ATS
- Perform an PPS-Request [Until here everything is fine and I get responses.]
Send an APDU-Command [btw. command works fine with my smartphone and an APP]
#Scan for cards (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL) #If a card is found if status == MIFAREReader.MI_OK: print "Card detected" TagType = (TagType >> 6) | 0 #(Länge der UID errechnen print "Tagtype: %s" % (TagType) # START ANTI-COLLISION AS OF ISO 14443 if TagType == 0: print "UID length is single -- starting ANTI-COLLISION CL1" (status,uid) = MIFAREReader.MFRC522_Anticoll() if status == MIFAREReader.MI_OK: print "Card read UID: %s,%s,%s,%s" % (uid[0], uid[1], uid[2], uid[3]) elif TagType == 1: # Ignore this part as there is no functionality by now print "CARD IS NOT SUPPORTED YET" (status,uid) = MIFAREReader.MFRC522_Anticoll() elif TagType == 2: print "CARD IS NOT SUPPORTED YET" (status,uid) = MIFAREReader.MFRC522_Anticoll() elif TagType == 3: print "CARD IS NOT SUPPORTED YET" (status,uid) = MIFAREReader.MFRC522_Anticoll() else: print "An unexpected error occured: UID length is not covered by ISO-14443." (size, APDU) = MIFAREReader.MFRC522_SelectTag(uid) print "Card selected" print "ISO 14443-4 Compatibility: %s" % (APDU) if APDU == 1: # Card supports ISO 14443-4 protocol [Problem could be here] #SEND RATS print "Sening RATS" RATS_Sequenz = [0xE0, 0x50] CRC_RATS = [] CRC_RATS = MIFAREReader.CalulateCRC(RATS_Sequenz) RATS_Sequenz.append(CRC_RATS[0]) RATS_Sequenz.append(CRC_RATS[1]) (stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, RATS_Sequenz) # Muss: Auswertung des ATS # PPS print "Initialisiere PPS-Kommando" PPSS_Sequenz = [0xD0, 0x11, 0x00] CRC_PPSS = [] CRC_PPSS = MIFAREReader.CalulateCRC(PPSS_Sequenz) PPSS_Sequenz.append(CRC_PPSS[0]) PPSS_Sequenz.append(CRC_PPSS[1]) (stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, PPSS_Sequenz) #PCB = [0x02] #PCB.append(PCB[0]) #PCB.append(PCB[1]) #(stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, PCB) command = [0xFF, 0x41, 0x00, 0x00, 0x00] # NOT THE COMMAND! Header = [0x00, 0x22, 0xC1, 0xA4, 0x12, 0x80, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x02, 0x83, 0x01, 0x02, 0x84, 0x01, 0x0D] #Command to be sent pOut = MIFAREReader.CalulateCRC(Header) Header.append(pOut[0]) Header.append(pOut[1]) (stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, (Header)) time.sleep(1) # Leftover from here / another non working try Body = [0x80, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x02, 0x83, 0x01, 0x02, 0x84, 0x01, 0x0D] #pOut = MIFAREReader.CalulateCRC(Body) #Body.append(pOut[0]) #Body.append(pOut[1]) #(stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, Body) elif APDU == 0: #HALT command = [0x50] pOut = MIFAREReader.CalulateCRC(command) command.append(pOut[0]) command.append(pOut[1]) (stat, res, leng) = MIFAREReader.MFRC522_ToCard(MIFAREReader.PCD_TRANSCEIVE, command) #WOP
This is the send function as found in the 'library':
def MFRC522_ToCard(self,command,sendData):
backData = []
backLen = 0
status = self.MI_ERR
irqEn = 0x00
waitIRq = 0x00
lastBits = None
n = 0
i = 0
if command == self.PCD_AUTHENT:
irqEn = 0x12
waitIRq = 0x10
if command == self.PCD_TRANSCEIVE:
irqEn = 0x77
waitIRq = 0x30
self.Write_MFRC522(self.CommIEnReg, irqEn|0x80)
self.ClearBitMask(self.CommIrqReg, 0x80)
self.SetBitMask(self.FIFOLevelReg, 0x80)
self.Write_MFRC522(self.CommandReg, self.PCD_IDLE);
while(i<len(sendData)):
self.Write_MFRC522(self.FIFODataReg, sendData[i])
i = i+1
self.Write_MFRC522(self.CommandReg, command)
if command == self.PCD_TRANSCEIVE:
self.SetBitMask(self.BitFramingReg, 0x80)
i = 2000
while True:
n = self.Read_MFRC522(self.CommIrqReg)
i = i - 1
if ~((i!=0) and ~(n&0x01) and ~(n&waitIRq)):
break
self.ClearBitMask(self.BitFramingReg, 0x80)
if i != 0:
if (self.Read_MFRC522(self.ErrorReg) & 0x1B)==0x00:
status = self.MI_OK
if n & irqEn & 0x01:
status = self.MI_NOTAGERR
if command == self.PCD_TRANSCEIVE:
n = self.Read_MFRC522(self.FIFOLevelReg)
lastBits = self.Read_MFRC522(self.ControlReg) & 0x07
if lastBits != 0:
backLen = (n-1)*8 + lastBits
else:
backLen = n*8
if n == 0:
n = 1
if n > self.MAX_LEN:
n = self.MAX_LEN
i = 0
while i<n:
backData.append(self.Read_MFRC522(self.FIFODataReg))
i = i + 1;
else:
status = self.MI_ERR
print"Status: %s, Data: %s, Length: %s" % (status, backData, backLen)
return (status,backData,backLen)
The command is send using the 'toCard' function of the code mentioned above with following structure:
APDU-Command + CRC-Bytes.
e.g. 0x00 [CLA], 0x22 [INS], 0xC1 [P1], 0xA4 [P2], 0x12 [Length], 0x80 [DATA, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x02, 0x83, 0x01, 0x02, 0x84, 0x01, 0x0D, CRC1, CRC2
I also tried sending the Command with an additional PCB or in multiple parts (e.g. Header first then body). I'm not sure if the structure of the APDU-Command is or if I forgot some part of the activation process as of ISO 14443. I'd be glad if anybody can help me.