Home › Forums › Ask the Flomies › MIFARE Classic Read block
Tagged: mifare-classic flojack
-
AuthorPosts
-
August 8, 2017 at 6:46 am #60613
Hey guys,
We’ve got a couple of FloJack BZR units here that we’re planning on using to take attendance for lectures. The idea is students can just tap their student card on their way into the theatre and they’re registered as attending in our LMS.
That hit a snag pretty quickly when I couldn’t figure out any way to actually authenticate using the “Pro” Flomio SDK. And also the Pro SDK is choc full of debugging messages so I could barely see anything happening anyway. Ah well, time to fall back to the lower level FTaR530 SDK.
Which was working great until…
Mifare_ReadBinary
is commented out in the header… and when I checked https://github.com/flomio/flomio_drivers_ios/blob/master/aR530/DOC/aR530_Developer_Guide_iOS_E_.pdf very closely I finally noticed the “removed in new SDK” next to read and update blocks.Which makes this kind of useless, doesn’t it? I can only read the first four bytes of a student ID, that’s not good enough. I was hoping there might be some magic APDU code to let me do this, but as far as I can tell MIFARE doesn’t actually use APDU at all and all the APDU codes you send to the FloJack are actually device-specific implementations…
Can you guys help at all? I literally just need to read block 0x28 of every card that comes near my reader. That doesn’t seem like it should be this difficult.
August 8, 2017 at 8:05 am #60619Hi,
Sorry that you haven’t had an easy experience so far, reading data from Mifare Classic tags with the Flojack BZR is a bit tricky but something I can help you with. First you need to ‘connect’ to the tag, using NFC_Card_Open, then you need to use NFC_Card_Transmit to send an APDU to it, most likely more than one.
Each mifare classic has a unique UUID which can be obtained by sending the APDU FFCA000000, you could potentially map this to a database of student IDs. If you need to read a different data block which contains a student ID, you will need to send different APDU commands. Mifare Classic has more security than other common tags, for example, a Mifare Ultralight tag, so you will need to first authenticate the block you are requesting, then request the data.
First
Load a key {FF FF FF FF FF FFh} into the volatile memory location 00h.
APDU = {FF 82 00 00 06 FF FF FF FF FF FFh}Then authenticate the block
To authenticate the Block 04h with a {TYPE A, key number 00h}.
// PC/SC V2.07
APDU = {FF 86 00 00 05 01 00 04 60 00h}Then
//Read 16 bytes from the binary block 04h (MIFARE Classic 1K or 4K)
APDU = {FF B0 00 04 10}
//Read 240 bytes starting from the binary block 80h (MIFARE Classic 4K)
//Block 80 to Block 8Eh (15 blocks)
APDU = {FF B0 00 80 F0}For more info, I will refer to you to docs from a different reader manufacturer here:
See section on reading Mifare Classic data: https://www.acs.com.hk/download-manual/4321/REF-ACR3x-1.03.pdfLet me know how you get on. Any more questions you have, I can reply here.
Kind Regards,
ScottAugust 9, 2017 at 4:03 am #60623Hi Scott,
Thanks, that was very helpful. I’ve now got my card working. It still seems to take a very, very long time though – probably a second or two. With an Arduino and a generic MFRC522 breakout, it takes maybe 1/10 of a second. Barely noticeable.
It seems like I have to send each command on a new iteration of the run loop. If I don’t add a DispatchQueue.main.async, none of the commands I issue are ever sent to the hardware.
All those runloop iterations are adding up. Is there any way I can make the whole thing run a lot faster?
Also – the app is using nearly 100% CPU. From Time Profiler it seems like the culprit is
-[FTAudioSession recv:recvLength:isHandshake:isGetPreResult:isAppendHeader:]
. Do you have any suggestions about how to reduce the amount of CPU usage by this method?- This reply was modified 7 years, 5 months ago by Morgan.
August 9, 2017 at 8:31 am #60625That’s not good!
Unfortunately you do need to use a polling loop to check for a tag. This is all implemented in the SDK so you don’t have to. We use a polling loop and a combination of dispatch tools to manage the audiojack session and APDUs, but you’re right, a second or two is about the correct time that each loop would take. This is due to the low data throughput of the audiojack interface and is one of the reasons we have moved to focus on FloBle Plus, BLE readers. Much much quicker!
I have not seen that problem of 100% CPU usage though, managing the audio session and APDU exchange with that delay is a headache I would recommend you try avoid!
Apologies this isn’t more positive advice.Scott
August 9, 2017 at 11:16 pm #60630I just switched back to the Flomio SDK code and I’m still seeing the 100% CPU. Here’s my code:
class RFIDController: NSObject, FmSessionManagerDelegate, FTaR530Delegate { let sessionManager = FmSessionManager()! var device: FmDevice? override init() { super.init() sessionManager.selectedDeviceType = .flojackAny sessionManager.delegate = self sessionManager.setConfiguration(["Scan Period": 1000]) sessionManager.createReaders() } func didFindTag(withUuid Uuid: String!, fromDevice deviceId: String!, withAtr Atr: String!, withError error: Error!) { DispatchQueue.main.async { print("found tag with \(Uuid)") } } func didFindTag(withData payload: [AnyHashable : Any]!, fromDevice deviceId: String!, withAtr Atr: String!, withError error: Error!) { DispatchQueue.main.async { print("found tag with some data") } } func didFindADataBlock(withNdef ndef: NdefMessage!, fromDevice serialNumber: String!, withError error: Error!) { DispatchQueue.main.async { print("found tag with some data") } } func didUpdateConnectedDevices(_ devices: [Any]!) { device = devices.first { $0 is FmDevice } as? FmDevice DispatchQueue.main.async { print("new connected devices: \(self.device!)") print(self.device!.device) } } func didReceiveReaderError(_ error: Error!) { DispatchQueue.main.async { print("received error \(error)") } } func didChange(_ status: CardStatus, fromDevice device: String!) { DispatchQueue.main.async { print("changed card status to \(status.rawValue) from \(device)") } }
And here’s the trace:
As you can see, it’s completely maxing out one of the CPU cores.
You can download the trace file here:
https://www.dropbox.com/sh/incdoiuasup9xpl/AADj35vZdyzTCLVkJ_u2FkQ2a?dl=0
August 19, 2017 at 8:48 pm #60712Hi Morgan, like Scott pointed out the CPU core is likely maxed out because the BZR driver is searching for an event. I’m not too familiar with Swift syntax so not sure what could be going wrong. The easiest way to resolve this is to move over to our FloBLE line of readers that carry out the tag polling loop on chip. This eliminates all of the headaches of the audio jack readers. Is there a particular reason you’re adamant about the FloJack?
best,
Richard -
AuthorPosts
You must be logged in to reply to this topic.