]> git.zerfleddert.de Git - proxmark3-svn/blame_incremental - armsrc/hitag2.c
fix LED signalling in hf 15 snoop and hf 14a snoop (#797)
[proxmark3-svn] / armsrc / hitag2.c
... / ...
CommitLineData
1//-----------------------------------------------------------------------------
2// This code is licensed to you under the terms of the GNU GPL, version 2 or,
3// at your option, any later version. See the LICENSE.txt file for the text of
4// the license.
5//-----------------------------------------------------------------------------
6// Hitag2 emulation (preliminary test version)
7//
8// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
9//-----------------------------------------------------------------------------
10// Hitag2 complete rewrite of the code
11// - Fixed modulation/encoding issues
12// - Rewrote code for transponder emulation
13// - Added snooping of transponder communication
14// - Added reader functionality
15//
16// (c) 2012 Roel Verdult
17//-----------------------------------------------------------------------------
18
19#include "proxmark3.h"
20#include "apps.h"
21#include "util.h"
22#include "hitag2.h"
23#include "string.h"
24#include "BigBuf.h"
25#include "fpgaloader.h"
26
27static bool bQuiet;
28
29static bool bCrypto;
30static bool bAuthenticating;
31static bool bPwd;
32static bool bSuccessful;
33
34
35
36struct hitag2_tag {
37 uint32_t uid;
38 enum {
39 TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr
40 TAG_STATE_ACTIVATING = 0x02 , // In activation phase (password mode), sent UID, awaiting reader password
41 TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands
42 TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
43 } state;
44 unsigned int active_sector;
45 byte_t crypto_active;
46 uint64_t cs;
47 byte_t sectors[12][4];
48};
49
50static struct hitag2_tag tag = {
51 .state = TAG_STATE_RESET,
52 .sectors = { // Password mode: | Crypto mode:
53 [0] = { 0x02, 0x4e, 0x02, 0x20}, // UID | UID
54 [1] = { 0x4d, 0x49, 0x4b, 0x52}, // Password RWD | 32 bit LSB key
55 [2] = { 0x20, 0xf0, 0x4f, 0x4e}, // Reserved | 16 bit MSB key, 16 bit reserved
56 [3] = { 0x0e, 0xaa, 0x48, 0x54}, // Configuration, password TAG | Configuration, password TAG
57 [4] = { 0x46, 0x5f, 0x4f, 0x4b}, // Data: F_OK
58 [5] = { 0x55, 0x55, 0x55, 0x55}, // Data: UUUU
59 [6] = { 0xaa, 0xaa, 0xaa, 0xaa}, // Data: ....
60 [7] = { 0x55, 0x55, 0x55, 0x55}, // Data: UUUU
61 [8] = { 0x00, 0x00, 0x00, 0x00}, // RSK Low
62 [9] = { 0x00, 0x00, 0x00, 0x00}, // RSK High
63 [10] = { 0x00, 0x00, 0x00, 0x00}, // RCF
64 [11] = { 0x00, 0x00, 0x00, 0x00}, // SYNC
65 },
66};
67
68static enum {
69 WRITE_STATE_START = 0x0,
70 WRITE_STATE_PAGENUM_WRITTEN,
71 WRITE_STATE_PROG
72} writestate;
73
74
75// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces.
76// Historically it used to be FREE_BUFFER_SIZE, which was 2744.
77#define AUTH_TABLE_LENGTH 2744
78static byte_t* auth_table;
79static size_t auth_table_pos = 0;
80static size_t auth_table_len = AUTH_TABLE_LENGTH;
81
82static byte_t password[4];
83static byte_t NrAr[8];
84static byte_t key[8];
85static byte_t writedata[4];
86static uint64_t cipher_state;
87
88/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
89// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
90// For educational purposes only.
91// No warranties or guarantees of any kind.
92// This code is released into the public domain by its author.
93
94// Basic macros:
95
96#define u8 uint8_t
97#define u32 uint32_t
98#define u64 uint64_t
99#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
100#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8))
101#define rev32(x) (rev16(x)+(rev16(x>>16)<<16))
102#define rev64(x) (rev32(x)+(rev32(x>>32)<<32))
103#define bit(x,n) (((x)>>(n))&1)
104#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1)
105#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31))
106#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63)))
107
108// Single bit Hitag2 functions:
109
110#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
111
112static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001
113static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001
114static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
115
116static u32 _f20 (const u64 x)
117{
118 u32 i5;
119
120 i5 = ((ht2_f4a >> i4 (x, 1, 2, 4, 5)) & 1)* 1
121 + ((ht2_f4b >> i4 (x, 7,11,13,14)) & 1)* 2
122 + ((ht2_f4b >> i4 (x,16,20,22,25)) & 1)* 4
123 + ((ht2_f4b >> i4 (x,27,28,30,32)) & 1)* 8
124 + ((ht2_f4a >> i4 (x,33,42,43,45)) & 1)*16;
125
126 return (ht2_f5c >> i5) & 1;
127}
128
129static u64 _hitag2_init (const u64 key, const u32 serial, const u32 IV)
130{
131 u32 i;
132 u64 x = ((key & 0xFFFF) << 32) + serial;
133
134 for (i = 0; i < 32; i++)
135 {
136 x >>= 1;
137 x += (u64) (_f20 (x) ^ (((IV >> i) ^ (key >> (i+16))) & 1)) << 47;
138 }
139 return x;
140}
141
142static u64 _hitag2_round (u64 *state)
143{
144 u64 x = *state;
145
146 x = (x >> 1) +
147 ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6)
148 ^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22)
149 ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41)
150 ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47);
151
152 *state = x;
153 return _f20 (x);
154}
155
156static u32 _hitag2_byte (u64 * x)
157{
158 u32 i, c;
159
160 for (i = 0, c = 0; i < 8; i++) c += (u32) _hitag2_round (x) << (i^7);
161 return c;
162}
163
164static int hitag2_reset(void)
165{
166 tag.state = TAG_STATE_RESET;
167 tag.crypto_active = 0;
168 return 0;
169}
170
171static int hitag2_init(void)
172{
173// memcpy(&tag, &resetdata, sizeof(tag));
174 hitag2_reset();
175 return 0;
176}
177
178static void hitag2_cipher_reset(struct hitag2_tag *tag, const byte_t *iv)
179{
180 uint64_t key = ((uint64_t)tag->sectors[2][2]) |
181 ((uint64_t)tag->sectors[2][3] << 8) |
182 ((uint64_t)tag->sectors[1][0] << 16) |
183 ((uint64_t)tag->sectors[1][1] << 24) |
184 ((uint64_t)tag->sectors[1][2] << 32) |
185 ((uint64_t)tag->sectors[1][3] << 40);
186 uint32_t uid = ((uint32_t)tag->sectors[0][0]) |
187 ((uint32_t)tag->sectors[0][1] << 8) |
188 ((uint32_t)tag->sectors[0][2] << 16) |
189 ((uint32_t)tag->sectors[0][3] << 24);
190 uint32_t iv_ = (((uint32_t)(iv[0]))) |
191 (((uint32_t)(iv[1])) << 8) |
192 (((uint32_t)(iv[2])) << 16) |
193 (((uint32_t)(iv[3])) << 24);
194 tag->cs = _hitag2_init(rev64(key), rev32(uid), rev32(iv_));
195}
196
197static int hitag2_cipher_authenticate(uint64_t* cs, const byte_t *authenticator_is)
198{
199 byte_t authenticator_should[4];
200 authenticator_should[0] = ~_hitag2_byte(cs);
201 authenticator_should[1] = ~_hitag2_byte(cs);
202 authenticator_should[2] = ~_hitag2_byte(cs);
203 authenticator_should[3] = ~_hitag2_byte(cs);
204 return (memcmp(authenticator_should, authenticator_is, 4) == 0);
205}
206
207static int hitag2_cipher_transcrypt(uint64_t* cs, byte_t *data, unsigned int bytes, unsigned int bits)
208{
209 int i;
210 for(i=0; i<bytes; i++) data[i] ^= _hitag2_byte(cs);
211 for(i=0; i<bits; i++) data[bytes] ^= _hitag2_round(cs) << (7-i);
212 return 0;
213}
214
215// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
216// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
217// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
218// T0 = TIMER_CLOCK1 / 125000 = 192
219#define T0 192
220
221#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
222#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
223
224#define HITAG_FRAME_LEN 20
225#define HITAG_T_STOP 36 /* T_EOF should be > 36 */
226#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */
227#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
228#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */
229//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */
230#define HITAG_T_EOF 80 /* T_EOF should be > 36 */
231#define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */
232#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */
233#define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */
234#define HITAG_T_PROG 614
235
236#define HITAG_T_TAG_ONE_HALF_PERIOD 10
237#define HITAG_T_TAG_TWO_HALF_PERIOD 25
238#define HITAG_T_TAG_THREE_HALF_PERIOD 41
239#define HITAG_T_TAG_FOUR_HALF_PERIOD 57
240
241#define HITAG_T_TAG_HALF_PERIOD 16
242#define HITAG_T_TAG_FULL_PERIOD 32
243
244#define HITAG_T_TAG_CAPTURE_ONE_HALF 13
245#define HITAG_T_TAG_CAPTURE_TWO_HALF 25
246#define HITAG_T_TAG_CAPTURE_THREE_HALF 41
247#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
248
249
250static void hitag_send_bit(int bit) {
251 LED_A_ON();
252 // Reset clock for the next bit
253 AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
254
255 // Fixed modulation, earlier proxmark version used inverted signal
256 if(bit == 0) {
257 // Manchester: Unloaded, then loaded |__--|
258 LOW(GPIO_SSC_DOUT);
259 while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD);
260 HIGH(GPIO_SSC_DOUT);
261 while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD);
262 } else {
263 // Manchester: Loaded, then unloaded |--__|
264 HIGH(GPIO_SSC_DOUT);
265 while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD);
266 LOW(GPIO_SSC_DOUT);
267 while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD);
268 }
269 LED_A_OFF();
270}
271
272static void hitag_send_frame(const byte_t* frame, size_t frame_len)
273{
274 // Send start of frame
275 for(size_t i=0; i<5; i++) {
276 hitag_send_bit(1);
277 }
278
279 // Send the content of the frame
280 for(size_t i=0; i<frame_len; i++) {
281 hitag_send_bit((frame[i/8] >> (7-(i%8)))&1);
282 }
283
284 // Drop the modulation
285 LOW(GPIO_SSC_DOUT);
286}
287
288
289static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
290{
291 byte_t rx_air[HITAG_FRAME_LEN];
292
293 // Copy the (original) received frame how it is send over the air
294 memcpy(rx_air,rx,nbytes(rxlen));
295
296 if(tag.crypto_active) {
297 hitag2_cipher_transcrypt(&(tag.cs),rx,rxlen/8,rxlen%8);
298 }
299
300 // Reset the transmission frame length
301 *txlen = 0;
302
303 // Try to find out which command was send by selecting on length (in bits)
304 switch (rxlen) {
305 // Received 11000 from the reader, request for UID, send UID
306 case 05: {
307 // Always send over the air in the clear plaintext mode
308 if(rx_air[0] != 0xC0) {
309 // Unknown frame ?
310 return;
311 }
312 *txlen = 32;
313 memcpy(tx,tag.sectors[0],4);
314 tag.crypto_active = 0;
315 }
316 break;
317
318 // Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number
319 case 10: {
320 unsigned int sector = (~( ((rx[0]<<2)&0x04) | ((rx[1]>>6)&0x03) ) & 0x07);
321 // Verify complement of sector index
322 if(sector != ((rx[0]>>3)&0x07)) {
323 //DbpString("Transmission error (read/write)");
324 return;
325 }
326
327 switch (rx[0] & 0xC6) {
328 // Read command: 11xx x00y
329 case 0xC0:
330 memcpy(tx,tag.sectors[sector],4);
331 *txlen = 32;
332 break;
333
334 // Inverted Read command: 01xx x10y
335 case 0x44:
336 for (size_t i=0; i<4; i++) {
337 tx[i] = tag.sectors[sector][i] ^ 0xff;
338 }
339 *txlen = 32;
340 break;
341
342 // Write command: 10xx x01y
343 case 0x82:
344 // Prepare write, acknowledge by repeating command
345 memcpy(tx,rx,nbytes(rxlen));
346 *txlen = rxlen;
347 tag.active_sector = sector;
348 tag.state=TAG_STATE_WRITING;
349 break;
350
351 // Unknown command
352 default:
353 Dbprintf("Unknown command: %02x %02x",rx[0],rx[1]);
354 return;
355 break;
356 }
357 }
358 break;
359
360 // Writing data or Reader password
361 case 32: {
362 if(tag.state == TAG_STATE_WRITING) {
363 // These are the sector contents to be written. We don't have to do anything else.
364 memcpy(tag.sectors[tag.active_sector],rx,nbytes(rxlen));
365 tag.state=TAG_STATE_RESET;
366 return;
367 } else {
368 // Received RWD password, respond with configuration and our password
369 if(memcmp(rx,tag.sectors[1],4) != 0) {
370 DbpString("Reader password is wrong");
371 return;
372 }
373 *txlen = 32;
374 memcpy(tx,tag.sectors[3],4);
375 }
376 }
377 break;
378
379 // Received RWD authentication challenge and respnse
380 case 64: {
381 // Store the authentication attempt
382 if (auth_table_len < (AUTH_TABLE_LENGTH-8)) {
383 memcpy(auth_table+auth_table_len,rx,8);
384 auth_table_len += 8;
385 }
386
387 // Reset the cipher state
388 hitag2_cipher_reset(&tag,rx);
389 // Check if the authentication was correct
390 if(!hitag2_cipher_authenticate(&(tag.cs),rx+4)) {
391 // The reader failed to authenticate, do nothing
392 Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]);
393 return;
394 }
395 // Succesful, but commented out reporting back to the Host, this may delay to much.
396 // Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]);
397
398 // Activate encryption algorithm for all further communication
399 tag.crypto_active = 1;
400
401 // Use the tag password as response
402 memcpy(tx,tag.sectors[3],4);
403 *txlen = 32;
404 }
405 break;
406 }
407
408// LogTraceHitag(rx,rxlen,0,0,false);
409// LogTraceHitag(tx,*txlen,0,0,true);
410
411 if(tag.crypto_active) {
412 hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen/8, *txlen%8);
413 }
414}
415
416static void hitag_reader_send_bit(int bit) {
417 LED_A_ON();
418 // Reset clock for the next bit
419 AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
420
421 // Binary puls length modulation (BPLM) is used to encode the data stream
422 // This means that a transmission of a one takes longer than that of a zero
423
424 // Enable modulation, which means, drop the field
425 HIGH(GPIO_SSC_DOUT);
426
427 // Wait for 4-10 times the carrier period
428 while(AT91C_BASE_TC0->TC_CV < T0*6);
429 // SpinDelayUs(8*8);
430
431 // Disable modulation, just activates the field again
432 LOW(GPIO_SSC_DOUT);
433
434 if(bit == 0) {
435 // Zero bit: |_-|
436 while(AT91C_BASE_TC0->TC_CV < T0*22);
437 // SpinDelayUs(16*8);
438 } else {
439 // One bit: |_--|
440 while(AT91C_BASE_TC0->TC_CV < T0*28);
441 // SpinDelayUs(22*8);
442 }
443 LED_A_OFF();
444}
445
446
447static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
448{
449 // Send the content of the frame
450 for(size_t i=0; i<frame_len; i++) {
451 hitag_reader_send_bit((frame[i/8] >> (7-(i%8)))&1);
452 }
453 // Send EOF
454 AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
455 // Enable modulation, which means, drop the field
456 HIGH(GPIO_SSC_DOUT);
457 // Wait for 4-10 times the carrier period
458 while(AT91C_BASE_TC0->TC_CV < T0*6);
459 // Disable modulation, just activates the field again
460 LOW(GPIO_SSC_DOUT);
461}
462
463size_t blocknr;
464
465static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
466 // Reset the transmission frame length
467 *txlen = 0;
468
469 // Try to find out which command was send by selecting on length (in bits)
470 switch (rxlen) {
471 // No answer, try to resurrect
472 case 0: {
473 // Stop if there is no answer (after sending password)
474 if (bPwd) {
475 DbpString("Password failed!");
476 return false;
477 }
478 *txlen = 5;
479 memcpy(tx,"\xc0",nbytes(*txlen));
480 } break;
481
482 // Received UID, tag password
483 case 32: {
484 if (!bPwd) {
485 *txlen = 32;
486 memcpy(tx,password,4);
487 bPwd = true;
488 memcpy(tag.sectors[blocknr],rx,4);
489 blocknr++;
490 } else {
491
492 if(blocknr == 1){
493 //store password in block1, the TAG answers with Block3, but we need the password in memory
494 memcpy(tag.sectors[blocknr],tx,4);
495 }else{
496 memcpy(tag.sectors[blocknr],rx,4);
497 }
498
499 blocknr++;
500 if (blocknr > 7) {
501 DbpString("Read succesful!");
502 bSuccessful = true;
503 return false;
504 }
505 *txlen = 10;
506 tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
507 tx[1] = ((blocknr^7) << 6);
508 }
509 } break;
510
511 // Unexpected response
512 default: {
513 Dbprintf("Uknown frame length: %d",rxlen);
514 return false;
515 } break;
516 }
517 return true;
518}
519
520static bool hitag2_write_page(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
521{
522 switch (writestate) {
523 case WRITE_STATE_START:
524 *txlen = 10;
525 tx[0] = 0x82 | (blocknr << 3) | ((blocknr^7) >> 2);
526 tx[1] = ((blocknr^7) << 6);
527 writestate = WRITE_STATE_PAGENUM_WRITTEN;
528 break;
529 case WRITE_STATE_PAGENUM_WRITTEN:
530 // Check if page number was received correctly
531 if ((rxlen == 10) &&
532 (rx[0] == (0x82 | (blocknr << 3) | ((blocknr^7) >> 2))) &&
533 (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) {
534 *txlen = 32;
535 memset(tx, 0, HITAG_FRAME_LEN);
536 memcpy(tx, writedata, 4);
537 writestate = WRITE_STATE_PROG;
538 } else {
539 Dbprintf("hitag2_write_page: Page number was not received correctly: rxlen=%d rx=%02x%02x%02x%02x",
540 rxlen, rx[0], rx[1], rx[2], rx[3]);
541 bSuccessful = false;
542 return false;
543 }
544 break;
545 case WRITE_STATE_PROG:
546 if (rxlen == 0) {
547 bSuccessful = true;
548 } else {
549 bSuccessful = false;
550 Dbprintf("hitag2_write_page: unexpected rx data (%d) after page write", rxlen);
551 }
552 return false;
553 default:
554 DbpString("hitag2_write_page: Unknown state %d");
555 bSuccessful = false;
556 return false;
557 }
558
559 return true;
560}
561
562static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen, bool write) {
563 // Reset the transmission frame length
564 *txlen = 0;
565
566 if(bCrypto) {
567 hitag2_cipher_transcrypt(&cipher_state,rx,rxlen/8,rxlen%8);
568
569 }
570
571 if (bCrypto && !bAuthenticating && write) {
572 if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
573 return false;
574 }
575 }
576 else
577 {
578
579 // Try to find out which command was send by selecting on length (in bits)
580 switch (rxlen) {
581 // No answer, try to resurrect
582 case 0:
583 {
584 // Stop if there is no answer while we are in crypto mode (after sending NrAr)
585 if (bCrypto) {
586 // Failed during authentication
587 if (bAuthenticating) {
588 DbpString("Authentication failed!");
589 return false;
590 } else {
591 // Failed reading a block, could be (read/write) locked, skip block and re-authenticate
592 if (blocknr == 1) {
593 // Write the low part of the key in memory
594 memcpy(tag.sectors[1],key+2,4);
595 } else if (blocknr == 2) {
596 // Write the high part of the key in memory
597 tag.sectors[2][0] = 0x00;
598 tag.sectors[2][1] = 0x00;
599 tag.sectors[2][2] = key[0];
600 tag.sectors[2][3] = key[1];
601 } else {
602 // Just put zero's in the memory (of the unreadable block)
603 memset(tag.sectors[blocknr],0x00,4);
604 }
605 blocknr++;
606 bCrypto = false;
607 }
608 } else {
609 *txlen = 5;
610 memcpy(tx,"\xc0",nbytes(*txlen));
611 }
612 break;
613 }
614 // Received UID, crypto tag answer
615 case 32: {
616 if (!bCrypto) {
617 uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40;
618 uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24;
619 Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t) ((rev64(ui64key)) >> 32), (uint32_t) ((rev64(ui64key)) & 0xffffffff), rev32(ui32uid));
620 cipher_state = _hitag2_init(rev64(ui64key), rev32(ui32uid), 0);
621 memset(tx,0x00,4);
622 memset(tx+4,0xff,4);
623 hitag2_cipher_transcrypt(&cipher_state, tx+4, 4, 0);
624 *txlen = 64;
625 bCrypto = true;
626 bAuthenticating = true;
627 } else {
628 // Check if we received answer tag (at)
629 if (bAuthenticating) {
630 bAuthenticating = false;
631 if (write) {
632 if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
633 return false;
634 }
635 break;
636 }
637 } else {
638 // Store the received block
639 memcpy(tag.sectors[blocknr],rx,4);
640 blocknr++;
641 }
642
643 if (blocknr > 7) {
644 DbpString("Read succesful!");
645 bSuccessful = true;
646 return false;
647 } else {
648 *txlen = 10;
649 tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
650 tx[1] = ((blocknr^7) << 6);
651 }
652 }
653 } break;
654
655 // Unexpected response
656 default: {
657 Dbprintf("Uknown frame length: %d",rxlen);
658 return false;
659 } break;
660 }
661 }
662
663 if(bCrypto) {
664 // We have to return now to avoid double encryption
665 if (!bAuthenticating) {
666 hitag2_cipher_transcrypt(&cipher_state,tx,*txlen/8,*txlen%8);
667 }
668 }
669
670 return true;
671}
672
673
674static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
675 // Reset the transmission frame length
676 *txlen = 0;
677
678 // Try to find out which command was send by selecting on length (in bits)
679 switch (rxlen) {
680 // No answer, try to resurrect
681 case 0: {
682 // Stop if there is no answer while we are in crypto mode (after sending NrAr)
683 if (bCrypto) {
684 DbpString("Authentication failed!");
685 return false;
686 }
687 *txlen = 5;
688 memcpy(tx,"\xc0",nbytes(*txlen));
689 } break;
690
691 // Received UID, crypto tag answer
692 case 32: {
693 if (!bCrypto) {
694 *txlen = 64;
695 memcpy(tx,NrAr,8);
696 bCrypto = true;
697 } else {
698 DbpString("Authentication succesful!");
699 // We are done... for now
700 return false;
701 }
702 } break;
703
704 // Unexpected response
705 default: {
706 Dbprintf("Uknown frame length: %d",rxlen);
707 return false;
708 } break;
709 }
710
711 return true;
712}
713
714
715static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
716
717 // Reset the transmission frame length
718 *txlen = 0;
719
720 // Try to find out which command was send by selecting on length (in bits)
721 switch (rxlen) {
722 // No answer, try to resurrect
723 case 0: {
724 // Stop if there is no answer while we are in crypto mode (after sending NrAr)
725 if (bCrypto) {
726 Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]);
727
728 // Removing failed entry from authentiations table
729 memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8);
730 auth_table_len -= 8;
731
732 // Return if we reached the end of the authentications table
733 bCrypto = false;
734 if (auth_table_pos == auth_table_len) {
735 return false;
736 }
737
738 // Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
739 memcpy(NrAr,auth_table+auth_table_pos,8);
740 }
741 *txlen = 5;
742 memcpy(tx,"\xc0",nbytes(*txlen));
743 } break;
744
745 // Received UID, crypto tag answer, or read block response
746 case 32: {
747 if (!bCrypto) {
748 *txlen = 64;
749 memcpy(tx,NrAr,8);
750 bCrypto = true;
751 } else {
752 Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]);
753 bCrypto = false;
754 if ((auth_table_pos+8) == auth_table_len) {
755 return false;
756 }
757 auth_table_pos += 8;
758 memcpy(NrAr,auth_table+auth_table_pos,8);
759 }
760 } break;
761
762 default: {
763 Dbprintf("Uknown frame length: %d",rxlen);
764 return false;
765 } break;
766 }
767
768 return true;
769}
770
771static bool hitag2_read_uid(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
772 // Reset the transmission frame length
773 *txlen = 0;
774
775 // Try to find out which command was send by selecting on length (in bits)
776 switch (rxlen) {
777 // No answer, try to resurrect
778 case 0: {
779 // Just starting or if there is no answer
780 *txlen = 5;
781 memcpy(tx,"\xc0",nbytes(*txlen));
782 } break;
783 // Received UID
784 case 32: {
785 // Check if we received answer tag (at)
786 if (bAuthenticating) {
787 bAuthenticating = false;
788 } else {
789 // Store the received block
790 memcpy(tag.sectors[blocknr],rx,4);
791 blocknr++;
792 }
793 if (blocknr > 0) {
794 //DbpString("Read successful!");
795 bSuccessful = true;
796 return false;
797 }
798 } break;
799 // Unexpected response
800 default: {
801 Dbprintf("Uknown frame length: %d",rxlen);
802 return false;
803 } break;
804 }
805 return true;
806}
807
808void SnoopHitag(uint32_t type) {
809 int frame_count;
810 int response;
811 int overflow;
812 bool rising_edge;
813 bool reader_frame;
814 int lastbit;
815 bool bSkip;
816 int tag_sof;
817 byte_t rx[HITAG_FRAME_LEN] = {0};
818 size_t rxlen=0;
819
820 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
821
822 // Clean up trace and prepare it for storing frames
823 set_tracing(true);
824 clear_trace();
825
826 auth_table_len = 0;
827 auth_table_pos = 0;
828
829 BigBuf_free();
830 auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
831 memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
832
833 DbpString("Starting Hitag2 snoop");
834 LED_D_ON();
835
836 // Set up eavesdropping mode, frequency divisor which will drive the FPGA
837 // and analog mux selection.
838 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
839 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
840 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
841 RELAY_OFF();
842
843 // Configure output pin that is connected to the FPGA (for modulating)
844 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
845 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
846
847 // Disable modulation, we are going to eavesdrop, not modulate ;)
848 LOW(GPIO_SSC_DOUT);
849
850 // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames
851 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
852 AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
853
854 // Disable timer during configuration
855 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
856
857 // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
858 // external trigger rising edge, load RA on rising edge of TIOA.
859 uint32_t t1_channel_mode = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH;
860 AT91C_BASE_TC1->TC_CMR = t1_channel_mode;
861
862 // Enable and reset counter
863 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
864
865 // Reset the received frame, frame count and timing info
866 frame_count = 0;
867 response = 0;
868 overflow = 0;
869 reader_frame = false;
870 lastbit = 1;
871 bSkip = true;
872 tag_sof = 4;
873
874 while(!BUTTON_PRESS()) {
875 // Watchdog hit
876 WDT_HIT();
877
878 // Receive frame, watch for at most T0*EOF periods
879 while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) {
880 // Check if rising edge in modulation is detected
881 if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
882 // Retrieve the new timing values
883 int ra = (AT91C_BASE_TC1->TC_RA/T0);
884
885 // Find out if we are dealing with a rising or falling edge
886 rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0;
887
888 // Shorter periods will only happen with reader frames
889 if (!reader_frame && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) {
890 // Switch from tag to reader capture
891 LED_C_OFF();
892 reader_frame = true;
893 memset(rx,0x00,sizeof(rx));
894 rxlen = 0;
895 }
896
897 // Only handle if reader frame and rising edge, or tag frame and falling edge
898 if (reader_frame != rising_edge) {
899 overflow += ra;
900 continue;
901 }
902
903 // Add the buffered timing values of earlier captured edges which were skipped
904 ra += overflow;
905 overflow = 0;
906
907 if (reader_frame) {
908 LED_B_ON();
909 // Capture reader frame
910 if(ra >= HITAG_T_STOP) {
911 if (rxlen != 0) {
912 //DbpString("wierd0?");
913 }
914 // Capture the T0 periods that have passed since last communication or field drop (reset)
915 response = (ra - HITAG_T_LOW);
916 } else if(ra >= HITAG_T_1_MIN ) {
917 // '1' bit
918 rx[rxlen / 8] |= 1 << (7-(rxlen%8));
919 rxlen++;
920 } else if(ra >= HITAG_T_0_MIN) {
921 // '0' bit
922 rx[rxlen / 8] |= 0 << (7-(rxlen%8));
923 rxlen++;
924 } else {
925 // Ignore wierd value, is to small to mean anything
926 }
927 } else {
928 LED_C_ON();
929 // Capture tag frame (manchester decoding using only falling edges)
930 if(ra >= HITAG_T_EOF) {
931 if (rxlen != 0) {
932 //DbpString("wierd1?");
933 }
934 // Capture the T0 periods that have passed since last communication or field drop (reset)
935 // We always recieve a 'one' first, which has the falling edge after a half period |-_|
936 response = ra-HITAG_T_TAG_HALF_PERIOD;
937 } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
938 // Manchester coding example |-_|_-|-_| (101)
939 rx[rxlen / 8] |= 0 << (7-(rxlen%8));
940 rxlen++;
941 rx[rxlen / 8] |= 1 << (7-(rxlen%8));
942 rxlen++;
943 } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
944 // Manchester coding example |_-|...|_-|-_| (0...01)
945 rx[rxlen / 8] |= 0 << (7-(rxlen%8));
946 rxlen++;
947 // We have to skip this half period at start and add the 'one' the second time
948 if (!bSkip) {
949 rx[rxlen / 8] |= 1 << (7-(rxlen%8));
950 rxlen++;
951 }
952 lastbit = !lastbit;
953 bSkip = !bSkip;
954 } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
955 // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
956 if (tag_sof) {
957 // Ignore bits that are transmitted during SOF
958 tag_sof--;
959 } else {
960 // bit is same as last bit
961 rx[rxlen / 8] |= lastbit << (7-(rxlen%8));
962 rxlen++;
963 }
964 } else {
965 // Ignore wierd value, is to small to mean anything
966 }
967 }
968 }
969 }
970
971 // Check if frame was captured
972 if(rxlen > 0) {
973 frame_count++;
974 if (!LogTraceHitag(rx,rxlen,response,0,reader_frame)) {
975 DbpString("Trace full");
976 break;
977 }
978
979 // Check if we recognize a valid authentication attempt
980 if (nbytes(rxlen) == 8) {
981 // Store the authentication attempt
982 if (auth_table_len < (AUTH_TABLE_LENGTH-8)) {
983 memcpy(auth_table+auth_table_len,rx,8);
984 auth_table_len += 8;
985 }
986 }
987
988 // Reset the received frame and response timing info
989 memset(rx,0x00,sizeof(rx));
990 response = 0;
991 reader_frame = false;
992 lastbit = 1;
993 bSkip = true;
994 tag_sof = 4;
995 overflow = 0;
996
997 LED_B_OFF();
998 LED_C_OFF();
999 } else {
1000 // Save the timer overflow, will be 0 when frame was received
1001 overflow += (AT91C_BASE_TC1->TC_CV/T0);
1002 }
1003 // Reset the frame length
1004 rxlen = 0;
1005 // Reset the timer to restart while-loop that receives frames
1006 AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
1007 }
1008 LED_A_ON();
1009 LED_B_OFF();
1010 LED_C_OFF();
1011 LED_D_OFF();
1012 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1013 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
1014 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1015 LED_A_OFF();
1016
1017// Dbprintf("frame received: %d",frame_count);
1018// Dbprintf("Authentication Attempts: %d",(auth_table_len/8));
1019// DbpString("All done");
1020}
1021
1022void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
1023 int frame_count;
1024 int response;
1025 int overflow;
1026 byte_t rx[HITAG_FRAME_LEN];
1027 size_t rxlen=0;
1028 byte_t tx[HITAG_FRAME_LEN];
1029 size_t txlen=0;
1030 bool bQuitTraceFull = false;
1031 bQuiet = false;
1032
1033 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
1034
1035 // Clean up trace and prepare it for storing frames
1036 set_tracing(true);
1037 clear_trace();
1038
1039 auth_table_len = 0;
1040 auth_table_pos = 0;
1041 byte_t* auth_table;
1042 BigBuf_free();
1043 auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
1044 memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
1045
1046 DbpString("Starting Hitag2 simulation");
1047 LED_D_ON();
1048 hitag2_init();
1049
1050 if (tag_mem_supplied) {
1051 DbpString("Loading hitag2 memory...");
1052 memcpy((byte_t*)tag.sectors,data,48);
1053 }
1054
1055 uint32_t block = 0;
1056 for (size_t i=0; i<12; i++) {
1057 for (size_t j=0; j<4; j++) {
1058 block <<= 8;
1059 block |= tag.sectors[i][j];
1060 }
1061 Dbprintf("| %d | %08x |",i,block);
1062 }
1063
1064 // Set up simulator mode, frequency divisor which will drive the FPGA
1065 // and analog mux selection.
1066 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
1067 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
1068 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
1069 RELAY_OFF();
1070
1071 // Configure output pin that is connected to the FPGA (for modulating)
1072 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
1073 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
1074
1075 // Disable modulation at default, which means release resistance
1076 LOW(GPIO_SSC_DOUT);
1077
1078 // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
1079 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
1080
1081 // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames
1082 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
1083 AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
1084
1085 // Disable timer during configuration
1086 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1087
1088 // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
1089 // external trigger rising edge, load RA on rising edge of TIOA.
1090 AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
1091
1092 // Reset the received frame, frame count and timing info
1093 memset(rx,0x00,sizeof(rx));
1094 frame_count = 0;
1095 response = 0;
1096 overflow = 0;
1097
1098 // Enable and reset counter
1099 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
1100
1101 while(!BUTTON_PRESS()) {
1102 // Watchdog hit
1103 WDT_HIT();
1104
1105 // Receive frame, watch for at most T0*EOF periods
1106 while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) {
1107 // Check if rising edge in modulation is detected
1108 if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
1109 // Retrieve the new timing values
1110 int ra = (AT91C_BASE_TC1->TC_RA/T0) + overflow;
1111 overflow = 0;
1112
1113 // Reset timer every frame, we have to capture the last edge for timing
1114 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
1115
1116 LED_B_ON();
1117
1118 // Capture reader frame
1119 if(ra >= HITAG_T_STOP) {
1120 if (rxlen != 0) {
1121 //DbpString("wierd0?");
1122 }
1123 // Capture the T0 periods that have passed since last communication or field drop (reset)
1124 response = (ra - HITAG_T_LOW);
1125 } else if(ra >= HITAG_T_1_MIN ) {
1126 // '1' bit
1127 rx[rxlen / 8] |= 1 << (7-(rxlen%8));
1128 rxlen++;
1129 } else if(ra >= HITAG_T_0_MIN) {
1130 // '0' bit
1131 rx[rxlen / 8] |= 0 << (7-(rxlen%8));
1132 rxlen++;
1133 } else {
1134 // Ignore wierd value, is to small to mean anything
1135 }
1136 }
1137 }
1138
1139 // Check if frame was captured
1140 if(rxlen > 4) {
1141 frame_count++;
1142 if (!bQuiet) {
1143 if (!LogTraceHitag(rx,rxlen,response,0,true)) {
1144 DbpString("Trace full");
1145 if (bQuitTraceFull) {
1146 break;
1147 } else {
1148 bQuiet = true;
1149 }
1150 }
1151 }
1152
1153 // Disable timer 1 with external trigger to avoid triggers during our own modulation
1154 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1155
1156 // Process the incoming frame (rx) and prepare the outgoing frame (tx)
1157 hitag2_handle_reader_command(rx,rxlen,tx,&txlen);
1158
1159 // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit,
1160 // not that since the clock counts since the rising edge, but T_Wait1 is
1161 // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low)
1162 // periods. The gap time T_Low varies (4..10). All timer values are in
1163 // terms of T0 units
1164 while(AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_WAIT_1-HITAG_T_LOW));
1165
1166 // Send and store the tag answer (if there is any)
1167 if (txlen) {
1168 // Transmit the tag frame
1169 hitag_send_frame(tx,txlen);
1170 // Store the frame in the trace
1171 if (!bQuiet) {
1172 if (!LogTraceHitag(tx,txlen,0,0,false)) {
1173 DbpString("Trace full");
1174 if (bQuitTraceFull) {
1175 break;
1176 } else {
1177 bQuiet = true;
1178 }
1179 }
1180 }
1181 }
1182
1183 // Reset the received frame and response timing info
1184 memset(rx,0x00,sizeof(rx));
1185 response = 0;
1186
1187 // Enable and reset external trigger in timer for capturing future frames
1188 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
1189 LED_B_OFF();
1190 }
1191 // Reset the frame length
1192 rxlen = 0;
1193 // Save the timer overflow, will be 0 when frame was received
1194 overflow += (AT91C_BASE_TC1->TC_CV/T0);
1195 // Reset the timer to restart while-loop that receives frames
1196 AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
1197 }
1198 LED_B_OFF();
1199 LED_D_OFF();
1200 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1201 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
1202 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1203
1204 DbpString("Sim Stopped");
1205
1206}
1207
1208void ReaderHitag(hitag_function htf, hitag_data* htd) {
1209 int frame_count;
1210 int response;
1211 byte_t rx[HITAG_FRAME_LEN];
1212 size_t rxlen=0;
1213 byte_t txbuf[HITAG_FRAME_LEN];
1214 byte_t* tx = txbuf;
1215 size_t txlen=0;
1216 int lastbit;
1217 bool bSkip;
1218 int reset_sof;
1219 int tag_sof;
1220 int t_wait = HITAG_T_WAIT_MAX;
1221 bool bStop = false;
1222 bool bQuitTraceFull = false;
1223
1224 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
1225 // Reset the return status
1226 bSuccessful = false;
1227
1228 // Clean up trace and prepare it for storing frames
1229 set_tracing(true);
1230 clear_trace();
1231
1232 //DbpString("Starting Hitag reader family");
1233
1234 // Check configuration
1235 switch(htf) {
1236 case RHT2F_PASSWORD: {
1237 Dbprintf("List identifier in password mode");
1238 memcpy(password,htd->pwd.password,4);
1239 blocknr = 0;
1240 bQuitTraceFull = false;
1241 bQuiet = false;
1242 bPwd = false;
1243 } break;
1244 case RHT2F_AUTHENTICATE: {
1245 DbpString("Authenticating using nr,ar pair:");
1246 memcpy(NrAr,htd->auth.NrAr,8);
1247 Dbhexdump(8,NrAr,false);
1248 bQuiet = false;
1249 bCrypto = false;
1250 bAuthenticating = false;
1251 bQuitTraceFull = true;
1252 } break;
1253 case RHT2F_CRYPTO:
1254 {
1255 DbpString("Authenticating using key:");
1256 memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code.
1257 Dbhexdump(6,key,false);
1258 blocknr = 0;
1259 bQuiet = false;
1260 bCrypto = false;
1261 bAuthenticating = false;
1262 bQuitTraceFull = true;
1263 } break;
1264 case RHT2F_TEST_AUTH_ATTEMPTS: {
1265 Dbprintf("Testing %d authentication attempts",(auth_table_len/8));
1266 auth_table_pos = 0;
1267 memcpy(NrAr, auth_table, 8);
1268 bQuitTraceFull = false;
1269 bQuiet = false;
1270 bCrypto = false;
1271 } break;
1272 case RHT2F_UID_ONLY: {
1273 blocknr = 0;
1274 bQuiet = false;
1275 bCrypto = false;
1276 bAuthenticating = false;
1277 bQuitTraceFull = true;
1278 } break;
1279 default: {
1280 Dbprintf("Error, unknown function: %d",htf);
1281 return;
1282 } break;
1283 }
1284
1285 LED_D_ON();
1286 hitag2_init();
1287
1288 // Configure output and enable pin that is connected to the FPGA (for modulating)
1289 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
1290 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
1291
1292 // Set fpga in edge detect with reader field, we can modulate as reader now
1293 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
1294
1295 // Set Frequency divisor which will drive the FPGA and analog mux selection
1296 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
1297 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
1298 RELAY_OFF();
1299
1300 // Disable modulation at default, which means enable the field
1301 LOW(GPIO_SSC_DOUT);
1302
1303 // Give it a bit of time for the resonant antenna to settle.
1304 SpinDelay(30);
1305
1306 // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
1307 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
1308
1309 // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
1310 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
1311 AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
1312
1313 // Disable timer during configuration
1314 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1315
1316 // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
1317 // external trigger rising edge, load RA on falling edge of TIOA.
1318 AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING;
1319
1320 // Enable and reset counters
1321 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
1322 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
1323
1324 // Reset the received frame, frame count and timing info
1325 frame_count = 0;
1326 response = 0;
1327 lastbit = 1;
1328
1329 // Tag specific configuration settings (sof, timings, etc.)
1330 if (htf < 10){
1331 // hitagS settings
1332 reset_sof = 1;
1333 t_wait = 200;
1334 //DbpString("Configured for hitagS reader");
1335 } else if (htf < 20) {
1336 // hitag1 settings
1337 reset_sof = 1;
1338 t_wait = 200;
1339 //DbpString("Configured for hitag1 reader");
1340 } else if (htf < 30) {
1341 // hitag2 settings
1342 reset_sof = 4;
1343 t_wait = HITAG_T_WAIT_2;
1344 //DbpString("Configured for hitag2 reader");
1345 } else {
1346 Dbprintf("Error, unknown hitag reader type: %d",htf);
1347 return;
1348 }
1349 uint8_t attempt_count=0;
1350 while(!bStop && !BUTTON_PRESS()) {
1351 // Watchdog hit
1352 WDT_HIT();
1353
1354 // Check if frame was captured and store it
1355 if(rxlen > 0) {
1356 frame_count++;
1357 if (!bQuiet) {
1358 if (!LogTraceHitag(rx,rxlen,response,0,false)) {
1359 DbpString("Trace full");
1360 if (bQuitTraceFull) {
1361 break;
1362 } else {
1363 bQuiet = true;
1364 }
1365 }
1366 }
1367 }
1368
1369 // By default reset the transmission buffer
1370 tx = txbuf;
1371 switch(htf) {
1372 case RHT2F_PASSWORD: {
1373 bStop = !hitag2_password(rx,rxlen,tx,&txlen);
1374 } break;
1375 case RHT2F_AUTHENTICATE: {
1376 bStop = !hitag2_authenticate(rx,rxlen,tx,&txlen);
1377 } break;
1378 case RHT2F_CRYPTO: {
1379 bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, false);
1380 } break;
1381 case RHT2F_TEST_AUTH_ATTEMPTS: {
1382 bStop = !hitag2_test_auth_attempts(rx,rxlen,tx,&txlen);
1383 } break;
1384 case RHT2F_UID_ONLY: {
1385 bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen);
1386 attempt_count++; //attempt 3 times to get uid then quit
1387 if (!bStop && attempt_count == 3) bStop = true;
1388 } break;
1389 default: {
1390 Dbprintf("Error, unknown function: %d",htf);
1391 return;
1392 } break;
1393 }
1394
1395 // Send and store the reader command
1396 // Disable timer 1 with external trigger to avoid triggers during our own modulation
1397 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1398
1399 // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
1400 // Since the clock counts since the last falling edge, a 'one' means that the
1401 // falling edge occured halfway the period. with respect to this falling edge,
1402 // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
1403 // All timer values are in terms of T0 units
1404 while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit)));
1405
1406 //Dbprintf("DEBUG: Sending reader frame");
1407
1408 // Transmit the reader frame
1409 hitag_reader_send_frame(tx,txlen);
1410
1411 // Enable and reset external trigger in timer for capturing future frames
1412 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
1413
1414 // Add transmitted frame to total count
1415 if(txlen > 0) {
1416 frame_count++;
1417 if (!bQuiet) {
1418 // Store the frame in the trace
1419 if (!LogTraceHitag(tx,txlen,HITAG_T_WAIT_2,0,true)) {
1420 if (bQuitTraceFull) {
1421 break;
1422 } else {
1423 bQuiet = true;
1424 }
1425 }
1426 }
1427 }
1428
1429 // Reset values for receiving frames
1430 memset(rx,0x00,sizeof(rx));
1431 rxlen = 0;
1432 lastbit = 1;
1433 bSkip = true;
1434 tag_sof = reset_sof;
1435 response = 0;
1436 //Dbprintf("DEBUG: Waiting to receive frame");
1437 uint32_t errorCount = 0;
1438
1439 // Receive frame, watch for at most T0*EOF periods
1440 while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) {
1441 // Check if falling edge in tag modulation is detected
1442 if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
1443 // Retrieve the new timing values
1444 int ra = (AT91C_BASE_TC1->TC_RA/T0);
1445
1446 // Reset timer every frame, we have to capture the last edge for timing
1447 AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
1448
1449 LED_B_ON();
1450
1451 // Capture tag frame (manchester decoding using only falling edges)
1452 if(ra >= HITAG_T_EOF) {
1453 if (rxlen != 0) {
1454 //Dbprintf("DEBUG: Wierd1");
1455 }
1456 // Capture the T0 periods that have passed since last communication or field drop (reset)
1457 // We always recieve a 'one' first, which has the falling edge after a half period |-_|
1458 response = ra-HITAG_T_TAG_HALF_PERIOD;
1459 } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
1460 // Manchester coding example |-_|_-|-_| (101)
1461
1462 //need to test to verify we don't exceed memory...
1463 //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
1464 // break;
1465 //}
1466 rx[rxlen / 8] |= 0 << (7-(rxlen%8));
1467 rxlen++;
1468 rx[rxlen / 8] |= 1 << (7-(rxlen%8));
1469 rxlen++;
1470 } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
1471 // Manchester coding example |_-|...|_-|-_| (0...01)
1472
1473 //need to test to verify we don't exceed memory...
1474 //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
1475 // break;
1476 //}
1477 rx[rxlen / 8] |= 0 << (7-(rxlen%8));
1478 rxlen++;
1479 // We have to skip this half period at start and add the 'one' the second time
1480 if (!bSkip) {
1481 rx[rxlen / 8] |= 1 << (7-(rxlen%8));
1482 rxlen++;
1483 }
1484 lastbit = !lastbit;
1485 bSkip = !bSkip;
1486 } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
1487 // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
1488
1489 //need to test to verify we don't exceed memory...
1490 //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
1491 // break;
1492 //}
1493 if (tag_sof) {
1494 // Ignore bits that are transmitted during SOF
1495 tag_sof--;
1496 } else {
1497 // bit is same as last bit
1498 rx[rxlen / 8] |= lastbit << (7-(rxlen%8));
1499 rxlen++;
1500 }
1501 } else {
1502 //Dbprintf("DEBUG: Wierd2");
1503 errorCount++;
1504 // Ignore wierd value, is to small to mean anything
1505 }
1506 }
1507 //if we saw over 100 wierd values break it probably isn't hitag...
1508 if (errorCount >100) break;
1509 // We can break this loop if we received the last bit from a frame
1510 if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) {
1511 if (rxlen>0) break;
1512 }
1513 }
1514 }
1515 //Dbprintf("DEBUG: Done waiting for frame");
1516
1517 LED_B_OFF();
1518 LED_D_OFF();
1519 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1520 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
1521 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1522 //Dbprintf("frame received: %d",frame_count);
1523 //DbpString("All done");
1524 if (bSuccessful)
1525 cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
1526 else
1527 cmd_send(CMD_ACK,bSuccessful,0,0,0,0);
1528
1529}
1530
1531void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
1532 int frame_count;
1533 int response;
1534 byte_t rx[HITAG_FRAME_LEN];
1535 size_t rxlen=0;
1536 byte_t txbuf[HITAG_FRAME_LEN];
1537 byte_t* tx = txbuf;
1538 size_t txlen=0;
1539 int lastbit;
1540 bool bSkip;
1541 int reset_sof;
1542 int tag_sof;
1543 int t_wait = HITAG_T_WAIT_MAX;
1544 bool bStop;
1545 bool bQuitTraceFull = false;
1546
1547 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
1548 // Reset the return status
1549 bSuccessful = false;
1550
1551 // Clean up trace and prepare it for storing frames
1552 set_tracing(true);
1553 clear_trace();
1554
1555 //DbpString("Starting Hitag reader family");
1556
1557 // Check configuration
1558 switch(htf) {
1559 case WHT2F_CRYPTO:
1560 {
1561 DbpString("Authenticating using key:");
1562 memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code.
1563 memcpy(writedata, htd->crypto.data, 4);
1564 Dbhexdump(6,key,false);
1565 blocknr = page;
1566 bQuiet = false;
1567 bCrypto = false;
1568 bAuthenticating = false;
1569 bQuitTraceFull = true;
1570 writestate = WRITE_STATE_START;
1571 } break;
1572 default: {
1573 Dbprintf("Error, unknown function: %d",htf);
1574 return;
1575 } break;
1576 }
1577
1578 LED_D_ON();
1579 hitag2_init();
1580
1581 // Configure output and enable pin that is connected to the FPGA (for modulating)
1582 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
1583 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
1584
1585 // Set fpga in edge detect with reader field, we can modulate as reader now
1586 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
1587
1588 // Set Frequency divisor which will drive the FPGA and analog mux selection
1589 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
1590 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
1591 RELAY_OFF();
1592
1593 // Disable modulation at default, which means enable the field
1594 LOW(GPIO_SSC_DOUT);
1595
1596 // Give it a bit of time for the resonant antenna to settle.
1597 SpinDelay(30);
1598
1599 // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
1600 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
1601
1602 // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
1603 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
1604 AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
1605
1606 // Disable timer during configuration
1607 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1608
1609 // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
1610 // external trigger rising edge, load RA on falling edge of TIOA.
1611 AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING;
1612
1613 // Enable and reset counters
1614 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
1615 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
1616
1617 // Reset the received frame, frame count and timing info
1618 frame_count = 0;
1619 response = 0;
1620 lastbit = 1;
1621 bStop = false;
1622
1623 // Tag specific configuration settings (sof, timings, etc.)
1624 if (htf < 10){
1625 // hitagS settings
1626 reset_sof = 1;
1627 t_wait = 200;
1628 //DbpString("Configured for hitagS reader");
1629 } else if (htf < 20) {
1630 // hitag1 settings
1631 reset_sof = 1;
1632 t_wait = 200;
1633 //DbpString("Configured for hitag1 reader");
1634 } else if (htf < 30) {
1635 // hitag2 settings
1636 reset_sof = 4;
1637 t_wait = HITAG_T_WAIT_2;
1638 //DbpString("Configured for hitag2 reader");
1639 } else {
1640 Dbprintf("Error, unknown hitag reader type: %d",htf);
1641 return;
1642 }
1643 while(!bStop && !BUTTON_PRESS()) {
1644 // Watchdog hit
1645 WDT_HIT();
1646
1647 // Check if frame was captured and store it
1648 if(rxlen > 0) {
1649 frame_count++;
1650 if (!bQuiet) {
1651 if (!LogTraceHitag(rx,rxlen,response,0,false)) {
1652 DbpString("Trace full");
1653 if (bQuitTraceFull) {
1654 break;
1655 } else {
1656 bQuiet = true;
1657 }
1658 }
1659 }
1660 }
1661
1662 // By default reset the transmission buffer
1663 tx = txbuf;
1664 switch(htf) {
1665 case WHT2F_CRYPTO: {
1666 bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, true);
1667 } break;
1668 default: {
1669 Dbprintf("Error, unknown function: %d",htf);
1670 return;
1671 } break;
1672 }
1673
1674 // Send and store the reader command
1675 // Disable timer 1 with external trigger to avoid triggers during our own modulation
1676 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1677
1678 // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
1679 // Since the clock counts since the last falling edge, a 'one' means that the
1680 // falling edge occured halfway the period. with respect to this falling edge,
1681 // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
1682 // All timer values are in terms of T0 units
1683 while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit)));
1684
1685 //Dbprintf("DEBUG: Sending reader frame");
1686
1687 // Transmit the reader frame
1688 hitag_reader_send_frame(tx,txlen);
1689
1690 // Enable and reset external trigger in timer for capturing future frames
1691 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
1692
1693 // Add transmitted frame to total count
1694 if(txlen > 0) {
1695 frame_count++;
1696 if (!bQuiet) {
1697 // Store the frame in the trace
1698 if (!LogTraceHitag(tx,txlen,HITAG_T_WAIT_2,0,true)) {
1699 if (bQuitTraceFull) {
1700 break;
1701 } else {
1702 bQuiet = true;
1703 }
1704 }
1705 }
1706 }
1707
1708 // Reset values for receiving frames
1709 memset(rx,0x00,sizeof(rx));
1710 rxlen = 0;
1711 lastbit = 1;
1712 bSkip = true;
1713 tag_sof = reset_sof;
1714 response = 0;
1715 //Dbprintf("DEBUG: Waiting to receive frame");
1716 uint32_t errorCount = 0;
1717
1718 // Receive frame, watch for at most T0*EOF periods
1719 while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) {
1720 // Check if falling edge in tag modulation is detected
1721 if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
1722 // Retrieve the new timing values
1723 int ra = (AT91C_BASE_TC1->TC_RA/T0);
1724
1725 // Reset timer every frame, we have to capture the last edge for timing
1726 AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
1727
1728 LED_B_ON();
1729
1730 // Capture tag frame (manchester decoding using only falling edges)
1731 if(ra >= HITAG_T_EOF) {
1732 if (rxlen != 0) {
1733 //Dbprintf("DEBUG: Wierd1");
1734 }
1735 // Capture the T0 periods that have passed since last communication or field drop (reset)
1736 // We always recieve a 'one' first, which has the falling edge after a half period |-_|
1737 response = ra-HITAG_T_TAG_HALF_PERIOD;
1738 } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
1739 // Manchester coding example |-_|_-|-_| (101)
1740
1741 //need to test to verify we don't exceed memory...
1742 //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
1743 // break;
1744 //}
1745 rx[rxlen / 8] |= 0 << (7-(rxlen%8));
1746 rxlen++;
1747 rx[rxlen / 8] |= 1 << (7-(rxlen%8));
1748 rxlen++;
1749 } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
1750 // Manchester coding example |_-|...|_-|-_| (0...01)
1751
1752 //need to test to verify we don't exceed memory...
1753 //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
1754 // break;
1755 //}
1756 rx[rxlen / 8] |= 0 << (7-(rxlen%8));
1757 rxlen++;
1758 // We have to skip this half period at start and add the 'one' the second time
1759 if (!bSkip) {
1760 rx[rxlen / 8] |= 1 << (7-(rxlen%8));
1761 rxlen++;
1762 }
1763 lastbit = !lastbit;
1764 bSkip = !bSkip;
1765 } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
1766 // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
1767
1768 //need to test to verify we don't exceed memory...
1769 //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
1770 // break;
1771 //}
1772 if (tag_sof) {
1773 // Ignore bits that are transmitted during SOF
1774 tag_sof--;
1775 } else {
1776 // bit is same as last bit
1777 rx[rxlen / 8] |= lastbit << (7-(rxlen%8));
1778 rxlen++;
1779 }
1780 } else {
1781 //Dbprintf("DEBUG: Wierd2");
1782 errorCount++;
1783 // Ignore wierd value, is to small to mean anything
1784 }
1785 }
1786 //if we saw over 100 wierd values break it probably isn't hitag...
1787 if (errorCount >100) break;
1788 // We can break this loop if we received the last bit from a frame
1789 if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) {
1790 if (rxlen>0) break;
1791 }
1792 }
1793
1794 // Wait some extra time for flash to be programmed
1795 if ((rxlen == 0) && (writestate == WRITE_STATE_PROG))
1796 {
1797 AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
1798 while(AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_PROG - HITAG_T_WAIT_MAX));
1799 }
1800 }
1801 //Dbprintf("DEBUG: Done waiting for frame");
1802
1803 LED_B_OFF();
1804 LED_D_OFF();
1805 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
1806 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
1807 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1808 //Dbprintf("frame received: %d",frame_count);
1809 //DbpString("All done");
1810 cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
1811}
Impressum, Datenschutz