2 This is a library to read 14443a tags. It can be used something like this
4 local reader = require('read14a')
5 result, err = reader.read1443a()
13 -- Loads the commands-library
14 local cmds
= require('commands')
15 local TIMEOUT
= 2000 -- Shouldn't take longer than 2 seconds
16 local ISO14A_COMMAND
= {
18 ISO14A_NO_DISCONNECT
= 2,
21 ISO14A_REQUEST_TRIGGER
= 0x10,
22 ISO14A_APPEND_CRC
= 0x20,
23 ISO14A_SET_TIMEOUT
= 0x40,
24 ISO14A_NO_SELECT
= 0x80,
25 ISO14A_TOPAZMODE
= 0x100
28 local ISO14443a_TYPES
= {}
29 ISO14443a_TYPES
[0x00] = "NXP MIFARE Ultralight | Ultralight C"
30 ISO14443a_TYPES
[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance"
31 ISO14443a_TYPES
[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)"
32 ISO14443a_TYPES
[0x08] = "NXP MIFARE CLASSIC 1k | Plus 2k"
33 ISO14443a_TYPES
[0x09] = "NXP MIFARE Mini 0.3k"
34 ISO14443a_TYPES
[0x10] = "NXP MIFARE Plus 2k"
35 ISO14443a_TYPES
[0x11] = "NXP MIFARE Plus 4k"
36 ISO14443a_TYPES
[0x18] = "NXP MIFARE Classic 4k | Plus 4k"
37 ISO14443a_TYPES
[0x20] = "NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k | JCOP 31/41"
38 ISO14443a_TYPES
[0x24] = "NXP MIFARE DESFire | DESFire EV1"
39 ISO14443a_TYPES
[0x28] = "JCOP31 or JCOP41 v2.3.1"
40 ISO14443a_TYPES
[0x38] = "Nokia 6212 or 6131 MIFARE CLASSIC 4K"
41 ISO14443a_TYPES
[0x88] = "Infineon MIFARE CLASSIC 1K"
42 ISO14443a_TYPES
[0x98] = "Gemplus MPCOS"
45 local function tostring_1443a(sak
)
46 return ISO14443a_TYPES
[sak
] or ("Unknown (SAK=%x)"):format(sak
)
49 local function parse1443a(data
)
52 Based on this struct :
61 } __attribute__((__packed__)) iso14a_card_select_t;
65 local count
,uid
,uidlen
, atqa
, sak
, ats_len
, ats
= bin
.unpack('H10CH2CC',data
)
66 uid
= uid
:sub(1,2*uidlen
)
67 --print("uid, atqa, sak: ",uid, atqa, sak)
68 --print("TYPE: ", tostring_1443a(sak))
69 return { uid
= uid
, atqa
= atqa
, sak
= sak
, name
= tostring_1443a(sak
)}
72 --- Sends a USBpacket to the device
73 -- @param command - the usb packet to send
74 -- @param ignoreresponse - if set to true, we don't read the device answer packet
75 -- which is usually recipe for fail. If not sent, the host will wait 2s for a
76 -- response of type CMD_ACK
77 -- @return packet,nil if successfull
78 -- nil, errormessage if unsuccessfull
80 local function sendToDevice(command
, ignoreresponse
)
81 core
.clearCommandBuffer()
82 local err
= core
.SendCommand(command
:getBytes())
87 if ignoreresponse
then return nil,nil end
89 local response
= core
.WaitForResponseTimeout(cmds
.CMD_ACK
,TIMEOUT
)
93 -- This function does a connect and retrieves som einfo
94 -- @param dont_disconnect - if true, does not disable the field
95 -- @return if successfull: an table containing card info
96 -- @return if unsuccessfull : nil, error
97 local function read14443a(dont_disconnect
)
98 local command
, result
, info
, err
, data
100 command
= Command
:new
{cmd
= cmds
.CMD_READER_ISO_14443a
,
101 arg1
= ISO14A_COMMAND
.ISO14A_CONNECT
}
102 if dont_disconnect
then
103 command
.arg1
= command
.arg1
+ ISO14A_COMMAND
.ISO14A_NO_DISCONNECT
105 local result
,err
= sendToDevice(command
)
107 local count
,cmd
,arg0
,arg1
,arg2
= bin
.unpack('LLLL',result
)
109 return nil, "iso14443a card select failed"
111 data
= string.sub(result
,count
)
112 info
, err
= parse1443a(data
)
114 err
="No response from card"
125 -- Waits for a mifare card to be placed within the vicinity of the reader.
126 -- @return if successfull: an table containing card info
127 -- @return if unsuccessfull : nil, error
128 local function waitFor14443a()
129 print("Waiting for card... press any key to quit")
130 while not core
.ukbhit() do
131 res
, err
= read14443a()
132 if res
then return res
end
133 -- err means that there was no response from card
135 return nil, "Aborted by user"
139 read1443a
= read14443a
,
141 waitFor14443a
= waitFor14443a
,
142 parse1443a
= parse1443a
,
143 sendToDevice
= sendToDevice
,
144 ISO14A_COMMAND
= ISO14A_COMMAND
,