-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnfc_smartcard.h
189 lines (143 loc) · 4.87 KB
/
nfc_smartcard.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#pragma once
#include <string>
#include <inttypes.h>
#include <stdexcept>
#include <nfc/nfc.h>
#include <nfc/nfc-types.h>
/**
* Exception class for reader related errors.
*/
class NFCError: public std::exception
{
public:
/** Constructor with human-readable reason message */
NFCError(const std::string& msg);
/** Returns reason why this was thrown. */
const char *what() const throw() {return _msg.c_str();}
~NFCError() throw() {}
protected:
/** Reason message */
std::string _msg;
};
/**
* Represents response APDU for ISO14443-4.
*/
class ResponseAPDU
{
public:
/** Parse response APDU from raw data */
ResponseAPDU(const std::string& data);
~ResponseAPDU() {}
/** Return whole status word */
uint16_t sw() const {return _sw;}
/** Return first byte of status word */
uint8_t sw1() const {return _sw >> 8;}
/** Return second byte of status word */
uint8_t sw2() const {return _sw & 0xFF;}
/** Return whether this is properly formed response */
bool valid() const {return _valid;}
/** Returns APDU data */
const std::string& data() const {return _data;}
private:
/** Data from response, without SW1 and SW2 */
std::string _data;
/** SW1 and SW2 */
uint16_t _sw;
/** Whether response APDU has had enough data to be valid */
bool _valid;
};
/**
* Represents one PN532 reader device. Config is taken from default
* libnfc-specified location. That usually means first device found is used.
*
* Config resides in /etc/nfc/libnfc.conf if installed from packages or
* /usr/local/etc/nfc/libnfc.conf if installed from source.
*
* A device is specified like this:
*
* device.connstring = pn532_uart:/dev/ttyACM0
* device.connstring = "pn532_spi:/dev/spidev0.0"
*
* Refer to libnfc documentation for setting up devices.
*/
class NFCDevice
{
public:
/**
* Initializes PN53x libnfc device and opens it, so you don't need to call
* open() after constructor.
*
* @throws NFCError if no device found or communication failed
*/
NFCDevice() throw(NFCError);
/** Destructor frees internal libnfc structures */
virtual ~NFCDevice();
/**
* Read UID of a card in field. If multiple cards are found, return UID of first one.
*
* If you are polling for cards with this, include some sleep in-between the calls (e.g. 0.1 sec).
*
* @returns binary string containing UID or empty if non-supported card
* present in reader field
* @throws NFCError if no cards in reader's field
*/
std::string scanUID() throw(NFCError);
/**
* Wait for one passive or emulated target and select it by reader.
*/
void selectPassiveTarget() throw(NFCError);
/**
* Send APDU to passive or emulated target. The target must be already
* selected by selectPassiveTarget() or scanUID().
*
* @param apdu command APDU to send
* @param returns response APDU received from target
* @throws NFCError if response APDU is too long or couldn't send APDU
*/
ResponseAPDU sendAPDU(const std::string& apdu) throw(NFCError);
/**
* Read NDEF message from Desfire.
*
* @returns NDEF message or empty string if there wasn't message
* @throws NFCError if there was problem communication with card or couldn't authenticate
*/
std::string readDesfireNDEF() throw(NFCError);
/** Open device explicitly. May be useful after explicit close */
void open() throw(NFCError);
/** Returns true iff device was opened and not unloaded. */
bool opened() const {return _opened && !_unloaded;}
/** Close reader. You need to reopen before reading again */
void close();
/**
* Unload all structures, close device. It's kind of explicit destructor
* since we can't be sure the destructor will be called in Python.
*/
void unload();
/**
* Specifies the number of polling (0x01 – 0xFE: 1 up to 254 polling, 0xFF:
* Endless polling)
*/
uint8_t pollNr;
/**
* Polling period when waiting for card in multiples of 150 ms.
* (0x01 – 0x0F: 150ms – 2.25s)
*/
uint8_t pollPeriod;
/**
* Timeout for waiting response to sent APDU. Value -1 means wait forever.
*/
int apduTimeout;
protected:
/** Modulations that specify cards accepted by reader */
static const nfc_modulation _modulations[5];
/** Number of modulations in _modulations array */
static const size_t _modulationsLen;
/** libnfc-specific opaque context */
nfc_context *_nfcContext;
/** Device opened by libnfc functions, may be NULL */
nfc_device *_nfcDevice;
/** Whether device has been successfully opened */
bool _opened;
/** Whether device and its internal libnfc structures have been unloaded */
bool _unloaded;
};