Add option to enable OTA mode at runtime
[doorlock_v1.git] / tag_handler.cpp
CommitLineData
bb5fbbec
JM
1#include <MFRC522.h>
2#include <FS.h>
3#include "config.h"
4
5typedef uint8_t byte_t;
6
7static const char * hex = "0123456789ABCDEF";
8
9
10int hexto(char c)
11{
12 if (c >= '0' && c <='9') return c - '0';
13 if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
14 if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
15}
16
17static const char * cardid(const byte_t uid[], byte_t len)
18{
19 static char text[21];
20 if (len > 10) return NULL;
21
22 char * p = text;
23 *(p++) = hex[ len ]; //DEBUG
24 *(p++) = ':'; //DEBUG
25 for (int i=0; i<len; i++) {
26 *(p++) = hex[ uid[i] >> 4 ];
27 *(p++) = hex[ uid[i] & 15 ];
28 }
29 *p = 0;
30 return text;
31}
32
33const char * uid_print(const MFRC522::Uid uid)
34{
35 return cardid(uid.uidByte, uid.size);
36}
37
38void uid_copy(MFRC522::Uid &a, const MFRC522::Uid b)
39{
40 a.size = b.size;
41 memcpy(a.uidByte, b.uidByte, b.size);
42}
43
44bool uid_compare(const MFRC522::Uid a, const MFRC522::Uid b)
45{
46 if (a.size != b.size) return 0;
47 if (a.size == 0 || b.size == 0) return 0;
48 return memcmp(a.uidByte, b.uidByte, a.size)==0?true:false;
49}
50
51void uid_zero(MFRC522::Uid &uid)
52{
53 uid.size = 0;
54}
55
56/* is this card id permitted */
57bool uid_auth(const MFRC522::Uid uid)
58{
59 // TODO: everything
60 // return card_auth(cardid(uid.uidByte, uid.size));
61 return true;
62}
63
64bool uid_isset(const MFRC522::Uid uid)
65{
66 return (uid.size!=0);
67}
68
69bool uid_visible(MFRC522 &reader, const MFRC522::Uid master)
70{
71 MFRC522::Uid uid;
72
73 // no tag given
74 if (master.size == 0) return false;
75
76 byte bufferATQA[2];
77 byte bufferSize = sizeof(bufferATQA);
78 byte status = 0;
79
80 SPI.begin();
81
82 // no tags in range to wakeup
83 if (reader.PICC_WakeupA(bufferATQA, &bufferSize) == MFRC522::STATUS_TIMEOUT) {
84 return false;
85 }
86
87 bool found = false;
88
89 uid_copy(uid, master);
90 if (reader.PICC_Select(&uid, uid.size * 8) == MFRC522::STATUS_OK) {
91 // something answered, but was it the right one
92 if (uid_compare(uid, master)) {
93 // yes, match
94 found=true;
95 } else {
96 // uid did not match
97 }
98 } else {
99 // nothing answered
100 }
101 reader.PICC_HaltA();
102 return found;
103}
104
105
106bool uid_fetch(MFRC522 &reader, MFRC522::Uid &uid, int count)
107{
108 SPI.begin();
109
110 byte bufferATQA[2];
111 byte bufferSize = sizeof(bufferATQA);
112 byte status = 0;
113
114 if (count == 0) {
115 status = reader.PICC_WakeupA(bufferATQA, &bufferSize);
116 } else {
117 status = reader.PICC_RequestA(bufferATQA, &bufferSize);
118 }
119
120 uid_zero(uid);
121 if (status != MFRC522::STATUS_OK && status != MFRC522::STATUS_COLLISION) {
122 if (status == MFRC522::STATUS_TIMEOUT) {
123 // Nobody listening
124 return false;
125 }
126 }
127
128 bool result = false;
129 if ( (status = reader.PICC_Select(&uid, 0)) == MFRC522::STATUS_OK ) {
130 result=true;
131 }
132 reader.PICC_HaltA();
133
134 return result;
135}
136
137
138bool uid_read(File &f, MFRC522::Uid &uid)
139{
140 char line[40];
141
142 int len = f.readBytesUntil('\n', line, 40);
143 if (len < 0 || len > 24) {
144 Serial.print("Invalid read: ");
145 Serial.println(len);
146 return false;
147 }
148 line[len]=0;
149
150 uid_zero(uid);
151 if (len == 0) {
152 // end of file
153 return false;
154 }
155
156 // minimum length is 4 bytes == 10 chars
157 if (len < 10) {
158 Serial.print(F("Read Card: bad line length="));
159 Serial.print(len);
160 Serial.print(" '");
161 Serial.print(line);
162 Serial.println("'");
163 return false;
164 }
165
166 // invalid format
167 if (line[1] != ':') {
168 Serial.print(F("Read Card: bad format '"));
169 Serial.print(line);
170 Serial.println("'");
171 return false;
172 }
173
174 int bytes = hexto(line[0]);
175
176 // invalid lengths: 4, 7, and 10 are the standards
177 if (bytes != 4 && bytes != 7 && bytes != 10) {
178 Serial.print(F("Read Card: bad size="));
179 Serial.print(bytes);
180 Serial.print(" '");
181 Serial.print(line);
182 Serial.println("'");
183 return false;
184 }
185
186 if (len < (bytes*2)+2) {
187 Serial.print(F("Read card: line too short. len="));
188 Serial.print(len);
189 Serial.print(F(" size="));
190 Serial.print(bytes);
191 Serial.print(" '");
192 Serial.print(line);
193 Serial.println("'");
194 return false;
195 }
196
197 uid.size = bytes;
198 byte * p = uid.uidByte;
199 int in = 2;
200
201 for (;bytes > 0;bytes--) {
202 int a,b;
203 a = hexto(line[in++]);
204 b = hexto(line[in++]);
205 if (a == -1 || b == -1) {
206 uid_zero(uid);
207
208 Serial.print(F("Read Card: Non Hex char in line '"));
209 Serial.print(line);
210 Serial.println("'");
211 return false;
212 }
213 *(p++) = a<<4 | b;
214 }
215
216#ifdef DEBUG
217 Serial.print(F("Loaded card '"));
218 Serial.print(line);
219 Serial.print("' as ");
220 Serial.println(uid_print(uid));
221#endif
222
223 return true;
224}
225
226bool uid_valid(MFRC522::Uid &uid)
227{
228#ifdef DEBUG
229 Serial.print(F("Opening file "));
230 Serial.println(KEYS_FILE);
231#endif
232
233 File f = SPIFFS.open(KEYS_FILE, "r");
234 // cant open the file, so card isnt there
235 if (!f) {
236 Serial.println(F("Cannot open cards file"));
237 return false;
238 }
239
240 MFRC522::Uid entry;
241 while ( uid_read(f, entry) ) {
242 if (uid_compare(uid, entry)) {
243 f.close();
244#ifdef DEBUG
245 Serial.println(F("Found card"));
246#endif
247 return true;
248 }
249 }
250
251#ifdef DEBUG
252 Serial.println(F("Card not found"));
253#endif
254 f.close();
255 return false;
256}
257