New code version which impliments a Wiegand card reader instead
[doorlock_v1.git] / tag_handler.cpp
1 #include <MFRC522.h>
2 #include <FS.h>
3 #include "config.h"
4
5 typedef uint8_t byte_t;
6
7 static const char * hex = "0123456789ABCDEF";
8
9
10 int 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
17 static 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
33 const char * uid_print(const MFRC522::Uid uid)
34 {
35   return cardid(uid.uidByte, uid.size);
36 }
37
38 void 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
44 bool 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
51 void uid_zero(MFRC522::Uid &uid)
52 {
53   uid.size = 0;
54 }
55
56 /* is this card id permitted */
57 bool uid_auth(const MFRC522::Uid uid)
58 {
59   // TODO:  everything
60  //  return card_auth(cardid(uid.uidByte, uid.size));
61  return true;
62 }
63
64 bool uid_isset(const MFRC522::Uid uid)
65 {
66   return (uid.size!=0);
67 }
68
69 bool 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
106 bool 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
138 bool 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
226 bool 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