]> git.zerfleddert.de Git - proxmark3-svn/blob - armsrc/i2c.c
Merge pull request #862 from pwpiwi/fix_iclass_sim
[proxmark3-svn] / armsrc / i2c.c
1 //-----------------------------------------------------------------------------
2 // Willok, June 2018
3 // Edits by Iceman, July 2018
4 //
5 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
6 // at your option, any later version. See the LICENSE.txt file for the text of
7 // the license.
8 //-----------------------------------------------------------------------------
9 // The main i2c code, for communications with smart card module
10 //-----------------------------------------------------------------------------
11
12 #include "i2c.h"
13
14 #include <stdint.h>
15 #include <stdbool.h>
16 #include "string.h" //for memset memcmp
17 #include "proxmark3.h"
18 #include "mifareutil.h" // for MF_DBGLEVEL
19 #include "BigBuf.h"
20 #include "apps.h"
21
22 #ifdef WITH_SMARTCARD
23 #include "smartcard.h"
24 #endif
25
26
27 #define GPIO_RST AT91C_PIO_PA1
28 #define GPIO_SCL AT91C_PIO_PA5
29 #define GPIO_SDA AT91C_PIO_PA7
30
31 #define SCL_H HIGH(GPIO_SCL)
32 #define SCL_L LOW(GPIO_SCL)
33 #define SDA_H HIGH(GPIO_SDA)
34 #define SDA_L LOW(GPIO_SDA)
35
36 #define SCL_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SCL)
37 #define SDA_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SDA)
38
39 #define I2C_ERROR "I2C_WaitAck Error"
40
41 static volatile unsigned long c;
42
43 // Ö±½ÓʹÓÃÑ­»·À´ÑÓʱ£¬Ò»¸öÑ­»· 6 ÌõÖ¸Á48M£¬ Delay=1 ´ó¸ÅΪ 200kbps
44 // timer.
45 // I2CSpinDelayClk(4) = 12.31us
46 // I2CSpinDelayClk(1) = 3.07us
47 static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
48 for (c = delay * 2; c; c--) {};
49 }
50
51 // communication delay functions
52 #define I2C_DELAY_1CLK I2CSpinDelayClk(1)
53 #define I2C_DELAY_2CLK I2CSpinDelayClk(2)
54 #define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
55
56 #define ISO7618_MAX_FRAME 255
57
58 // try i2c bus recovery at 100kHz = 5uS high, 5uS low
59 static void I2C_recovery(void) {
60
61 DbpString("Performing i2c bus recovery");
62
63 // reset I2C
64 SDA_H; SCL_H;
65
66 //9nth cycle acts as NACK
67 for (int i = 0; i < 10; i++) {
68 SCL_H; WaitUS(5);
69 SCL_L; WaitUS(5);
70 }
71
72 //a STOP signal (SDA from low to high while CLK is high)
73 SDA_L; WaitUS(5);
74 SCL_H; WaitUS(2);
75 SDA_H; WaitUS(2);
76
77 bool isok = (SCL_read && SDA_read);
78 if (!SDA_read)
79 DbpString("I2C bus recovery error: SDA still LOW");
80 if (!SCL_read)
81 DbpString("I2C bus recovery error: SCL still LOW");
82 if (isok)
83 DbpString("I2C bus recovery complete");
84 }
85
86 static void I2C_init(void) {
87 // Configure reset pin
88 AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST; // disable pull up resistor
89 AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST; // push-pull output (multidriver disabled)
90
91 // Configure SCL and SDA pins
92 AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA); // enable pull up resistor
93 AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA); // open drain output (multidriver enabled) - requires external pull up resistor
94
95 // set all three outputs to high
96 AT91C_BASE_PIOA->PIO_SODR |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
97
98 // configure all three pins as output, controlled by PIOA
99 AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
100 AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
101
102 bool isok = (SCL_read && SDA_read);
103 if ( !isok )
104 I2C_recovery();
105
106 }
107
108 // set the reset state
109 static void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
110 if (LineRST)
111 HIGH(GPIO_RST);
112 else
113 LOW(GPIO_RST);
114
115 if (LineSCK)
116 HIGH(GPIO_SCL);
117 else
118 LOW(GPIO_SCL);
119
120 if (LineSDA)
121 HIGH(GPIO_SDA);
122 else
123 LOW(GPIO_SDA);
124 }
125
126 // Reset the SIM_Adapter, then enter the main program
127 // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter.
128 static void I2C_Reset_EnterMainProgram(void) {
129 StartTicks();
130 I2C_init();
131 I2C_SetResetStatus(0, 0, 0);
132 WaitMS(30);
133 I2C_SetResetStatus(1, 0, 0);
134 WaitMS(30);
135 I2C_SetResetStatus(1, 1, 1);
136 WaitMS(10);
137 }
138
139 // Wait for the clock to go High.
140 static bool WaitSCL_H_delay(uint32_t delay) {
141 while (delay--) {
142 if (SCL_read) {
143 return true;
144 }
145 I2C_DELAY_1CLK;
146 }
147 return false;
148 }
149
150 // 15000 * 3.07us = 46050us. 46.05ms
151 static bool WaitSCL_H(void) {
152 return WaitSCL_H_delay(15000);
153 }
154
155 bool WaitSCL_L_delay(uint32_t delay) {
156 while (delay--) {
157 if (!SCL_read) {
158 return true;
159 }
160 I2C_DELAY_1CLK;
161 }
162 return false;
163 }
164
165 bool WaitSCL_L(void) {
166 return WaitSCL_L_delay(15000);
167 }
168
169 static bool I2C_Start(void) {
170
171 I2C_DELAY_XCLK(4);
172 SDA_H; I2C_DELAY_1CLK;
173 SCL_H;
174 if (!WaitSCL_H()) return false;
175
176 I2C_DELAY_2CLK;
177
178 if (!SCL_read) return false;
179 if (!SDA_read) return false;
180
181 SDA_L; I2C_DELAY_2CLK;
182 return true;
183 }
184
185 // send i2c STOP
186 static void I2C_Stop(void) {
187 SCL_L; I2C_DELAY_2CLK;
188 SDA_L; I2C_DELAY_2CLK;
189 SCL_H; I2C_DELAY_2CLK;
190 if (!WaitSCL_H()) return;
191 SDA_H;
192 I2C_DELAY_XCLK(8);
193 }
194
195 static bool I2C_WaitAck(void) {
196 SCL_L; I2C_DELAY_1CLK;
197 SDA_H; I2C_DELAY_1CLK;
198 SCL_H;
199 if (!WaitSCL_H())
200 return false;
201
202 I2C_DELAY_2CLK;
203 I2C_DELAY_2CLK;
204 if (SDA_read) {
205 SCL_L;
206 return false;
207 }
208 SCL_L;
209 return true;
210 }
211
212 static void I2C_SendByte(uint8_t data) {
213 uint8_t bits = 8;
214
215 while (bits--) {
216 SCL_L;
217 I2C_DELAY_1CLK;
218
219 if (data & 0x80)
220 SDA_H;
221 else
222 SDA_L;
223
224 data <<= 1;
225
226 I2C_DELAY_1CLK;
227
228 SCL_H;
229 if (!WaitSCL_H())
230 return;
231
232 I2C_DELAY_2CLK;
233 }
234 SCL_L;
235 }
236
237 bool I2C_is_available(void) {
238 I2C_Reset_EnterMainProgram();
239 if (!I2C_Start()) // some other device is active on the bus
240 return true;
241 I2C_SendByte(I2C_DEVICE_ADDRESS_MAIN & 0xFE);
242 if (!I2C_WaitAck()) { // no response from smartcard reader
243 I2C_Stop();
244 return false;
245 }
246 I2C_Stop();
247 return true;
248 }
249
250 #ifdef WITH_SMARTCARD
251 // Reset the SIM_Adapter, then enter the bootloader program
252 // Reserve£ºFor firmware update.
253 static void I2C_Reset_EnterBootloader(void) {
254 I2C_SetResetStatus(0, 1, 1);
255 WaitMS(100);
256 I2C_SetResetStatus(1, 1, 1);
257 WaitMS(10);
258 }
259
260 // Wait max 1800ms or until SCL goes LOW.
261 // It timeout reading response from card
262 // Which ever comes first
263 bool WaitSCL_L_timeout(void){
264 volatile uint16_t delay = 1800;
265 while ( delay-- ) {
266 // exit on SCL LOW
267 if (!SCL_read)
268 return true;
269
270 WaitMS(1);
271 }
272 return (delay == 0);
273 }
274
275 static bool I2C_WaitForSim() {
276 // wait for data from card
277 if (!WaitSCL_L_timeout())
278 return false;
279
280 // 8051 speaks with smart card.
281 // 1000*50*3.07 = 153.5ms
282 // 1byte transfer == 1ms with max frame being 256bytes
283 if (!WaitSCL_H_delay(10 * 1000 * 50))
284 return false;
285
286 return true;
287 }
288
289 // Send i2c ACK
290 static void I2C_Ack(void) {
291 SCL_L; I2C_DELAY_2CLK;
292 SDA_L; I2C_DELAY_2CLK;
293 SCL_H; I2C_DELAY_2CLK;
294 if (!WaitSCL_H()) return;
295 SCL_L; I2C_DELAY_2CLK;
296 }
297
298 // Send i2c NACK
299 static void I2C_NoAck(void) {
300 SCL_L; I2C_DELAY_2CLK;
301 SDA_H; I2C_DELAY_2CLK;
302 SCL_H; I2C_DELAY_2CLK;
303 if (!WaitSCL_H()) return;
304 SCL_L; I2C_DELAY_2CLK;
305 }
306
307 static int16_t I2C_ReadByte(void) {
308 uint8_t bits = 8, b = 0;
309
310 SDA_H;
311 while (bits--) {
312 b <<= 1;
313 SCL_L;
314 if (!WaitSCL_L()) return -2;
315
316 I2C_DELAY_1CLK;
317
318 SCL_H;
319 if (!WaitSCL_H()) return -1;
320
321 I2C_DELAY_1CLK;
322 if (SDA_read)
323 b |= 0x01;
324 }
325 SCL_L;
326 return b;
327 }
328
329 // Sends one byte ( command to be written, SlaveDevice address)
330 static bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) {
331 bool bBreak = true;
332 do {
333 if (!I2C_Start())
334 return false;
335
336 I2C_SendByte(device_address & 0xFE);
337 if (!I2C_WaitAck())
338 break;
339
340 I2C_SendByte(device_cmd);
341 if (!I2C_WaitAck())
342 break;
343
344 bBreak = false;
345 } while (false);
346
347 I2C_Stop();
348 if (bBreak) {
349 if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR);
350 return false;
351 }
352 return true;
353 }
354
355 // Sends 1 byte data (Data to be written, command to be written , SlaveDevice address ).
356 static bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
357 bool bBreak = true;
358 do {
359 if (!I2C_Start())
360 return false;
361
362 I2C_SendByte(device_address & 0xFE);
363 if (!I2C_WaitAck())
364 break;
365
366 I2C_SendByte(device_cmd);
367 if (!I2C_WaitAck())
368 break;
369
370 I2C_SendByte(data);
371 if (!I2C_WaitAck())
372 break;
373
374 bBreak = false;
375 } while (false);
376
377 I2C_Stop();
378 if (bBreak) {
379 if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR);
380 return false;
381 }
382 return true;
383 }
384
385 //Sends a string of data (Array, length, command to be written , SlaveDevice address ).
386 // len = uint8 (max buffer to write 256bytes)
387 static bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
388 bool bBreak = true;
389 do {
390 if (!I2C_Start())
391 return false;
392
393 I2C_SendByte(device_address & 0xFE);
394 if (!I2C_WaitAck())
395 break;
396
397 I2C_SendByte(device_cmd);
398 if (!I2C_WaitAck())
399 break;
400
401 while (len) {
402
403 I2C_SendByte(*data);
404 if (!I2C_WaitAck())
405 break;
406
407 len--;
408 data++;
409 }
410
411 if (len == 0)
412 bBreak = false;
413 } while (false);
414
415 I2C_Stop();
416 if (bBreak) {
417 if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR);
418 return false;
419 }
420 return true;
421 }
422
423 // read 1 strings of data (Data array, Readout length, command to be written , SlaveDevice address ).
424 // len = uint8 (max buffer to read 256bytes)
425 static int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
426
427 if ( !data || len == 0 )
428 return 0;
429
430 // extra wait 500us (514us measured)
431 // 200us (xx measured)
432 WaitUS(600);
433 bool bBreak = true;
434 uint16_t readcount = 0;
435
436 do {
437 if (!I2C_Start())
438 return 0;
439
440 // 0xB0 / 0xC0 == i2c write
441 I2C_SendByte(device_address & 0xFE);
442 if (!I2C_WaitAck())
443 break;
444
445 I2C_SendByte(device_cmd);
446 if (!I2C_WaitAck())
447 break;
448
449 // 0xB1 / 0xC1 == i2c read
450 I2C_Start();
451 I2C_SendByte(device_address | 1);
452 if (!I2C_WaitAck())
453 break;
454
455 bBreak = false;
456 } while (false);
457
458 if (bBreak) {
459 I2C_Stop();
460 if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR);
461 return 0;
462 }
463
464 while (len) {
465
466 int16_t tmp = I2C_ReadByte();
467 if ( tmp < 0 )
468 return tmp;
469
470 *data = (uint8_t)tmp & 0xFF;
471
472 len--;
473
474 // ¶ÁÈ¡µÄµÚÒ»¸ö×Ö½ÚΪºóÐø³¤¶È
475 // The first byte in response is the message length
476 if (!readcount && (len > *data)) {
477 len = *data;
478 } else {
479 data++;
480 }
481 readcount++;
482
483 // acknowledgements. After last byte send NACK.
484 if (len == 0)
485 I2C_NoAck();
486 else
487 I2C_Ack();
488 }
489
490 I2C_Stop();
491
492 // return bytecount - first byte (which is length byte)
493 return --readcount;
494 }
495
496 static int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
497 //START, 0xB0, 0x00, 0x00, START, 0xB1, xx, yy, zz, ......, STOP
498 bool bBreak = true;
499 uint8_t readcount = 0;
500
501 // sending
502 do {
503 if (!I2C_Start())
504 return 0;
505
506 // 0xB0 / 0xC0 i2c write
507 I2C_SendByte(device_address & 0xFE);
508 if (!I2C_WaitAck())
509 break;
510
511 I2C_SendByte(msb);
512 if (!I2C_WaitAck())
513 break;
514
515 I2C_SendByte(lsb);
516 if (!I2C_WaitAck())
517 break;
518
519 // 0xB1 / 0xC1 i2c read
520 I2C_Start();
521 I2C_SendByte(device_address | 1);
522 if (!I2C_WaitAck())
523 break;
524
525 bBreak = false;
526 } while (false);
527
528 if (bBreak) {
529 I2C_Stop();
530 if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR);
531 return 0;
532 }
533
534 // reading
535 while (len) {
536
537 int16_t tmp = I2C_ReadByte();
538 if ( tmp < 0 )
539 return tmp;
540
541 *data = (uint8_t)tmp & 0xFF;
542
543 data++;
544 readcount++;
545 len--;
546
547 // acknowledgements. After last byte send NACK.
548 if (len == 0)
549 I2C_NoAck();
550 else
551 I2C_Ack();
552 }
553
554 I2C_Stop();
555 return readcount;
556 }
557
558 static bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
559 //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP
560 bool bBreak = true;
561
562 do {
563 if (!I2C_Start())
564 return false;
565
566 // 0xB0 == i2c write
567 I2C_SendByte(device_address & 0xFE);
568 if (!I2C_WaitAck())
569 break;
570
571 I2C_SendByte(msb);
572 if (!I2C_WaitAck())
573 break;
574
575 I2C_SendByte(lsb);
576 if (!I2C_WaitAck())
577 break;
578
579 while (len) {
580 I2C_SendByte(*data);
581 if (!I2C_WaitAck())
582 break;
583
584 len--;
585 data++;
586 }
587
588 if (len == 0)
589 bBreak = false;
590 } while (false);
591
592 I2C_Stop();
593 if (bBreak) {
594 if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR);
595 return false;
596 }
597 return true;
598 }
599
600 void I2C_print_status(void) {
601 DbpString("Smart card module (ISO 7816)");
602 uint8_t resp[] = {0,0,0,0};
603 I2C_Reset_EnterMainProgram();
604 uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN);
605 if ( len > 0 )
606 Dbprintf(" version.................v%x.%02x", resp[0], resp[1]);
607 else
608 DbpString(" version.................FAILED");
609 }
610
611 // Will read response from smart card module, retries 3 times to get the data.
612 static bool sc_rx_bytes(uint8_t* dest, uint8_t *destlen) {
613 uint8_t i = 3;
614 int16_t len = 0;
615 while (i--) {
616
617 I2C_WaitForSim();
618
619 len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
620
621 if ( len > 1 ){
622 break;
623 } else if ( len == 1 ) {
624 continue;
625 } else if ( len <= 0 ) {
626 return false;
627 }
628 }
629 // after three
630 if ( len <= 1 )
631 return false;
632
633 *destlen = (uint8_t)len & 0xFF;
634 return true;
635 }
636
637 static bool GetATR(smart_card_atr_t *card_ptr) {
638
639 if ( !card_ptr ) {
640 return false;
641 }
642
643 card_ptr->atr_len = 0;
644 memset(card_ptr->atr, 0, sizeof(card_ptr->atr));
645
646 // Send ATR
647 // start [C0 01] stop start C1 len aa bb cc stop]
648 I2C_WriteCmd(I2C_DEVICE_CMD_GENERATE_ATR, I2C_DEVICE_ADDRESS_MAIN);
649
650 // wait for sim card to answer.
651 // 1byte = 1ms, max frame 256bytes. Should wait 256ms at least just in case.
652 if (!I2C_WaitForSim())
653 return false;
654
655 // read bytes from module
656 uint8_t len = sizeof(card_ptr->atr);
657 if ( !sc_rx_bytes(card_ptr->atr, &len) )
658 return false;
659
660 card_ptr->atr_len = len;
661 LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
662
663 return true;
664 }
665
666 void SmartCardAtr(void) {
667 smart_card_atr_t card;
668 LED_D_ON();
669 clear_trace();
670 set_tracing(true);
671 I2C_Reset_EnterMainProgram();
672 bool isOK = GetATR( &card );
673 cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
674 set_tracing(false);
675 LEDsoff();
676 }
677
678 void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) {
679
680 LED_D_ON();
681
682 uint8_t len = 0;
683 uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME);
684 smartcard_command_t flags = arg0;
685
686 if ((flags & SC_CONNECT))
687 clear_trace();
688
689 set_tracing(true);
690
691 if ((flags & SC_CONNECT)) {
692
693 I2C_Reset_EnterMainProgram();
694
695 if ((flags & SC_SELECT)) {
696 smart_card_atr_t card;
697 bool gotATR = GetATR( &card );
698 //cmd_send(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
699 if ( !gotATR )
700 goto OUT;
701 }
702 }
703
704 if ((flags & SC_RAW) || (flags & SC_RAW_T0)) {
705
706 LogTrace(data, arg1, 0, 0, NULL, true);
707
708 // Send raw bytes
709 // asBytes = A0 A4 00 00 02
710 // arg1 = len 5
711 bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN);
712 if ( !res && MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR);
713
714 // read bytes from module
715 len = ISO7618_MAX_FRAME;
716 res = sc_rx_bytes(resp, &len);
717 if ( res ) {
718 LogTrace(resp, len, 0, 0, NULL, false);
719 } else {
720 len = 0;
721 }
722 }
723 OUT:
724 cmd_send(CMD_ACK, len, 0, 0, resp, len);
725 BigBuf_free();
726 set_tracing(false);
727 LEDsoff();
728 }
729
730 void SmartCardUpgrade(uint64_t arg0) {
731
732 LED_C_ON();
733
734 #define I2C_BLOCK_SIZE 128
735 // write. Sector0, with 11,22,33,44
736 // erase is 128bytes, and takes 50ms to execute
737
738 I2C_Reset_EnterBootloader();
739
740 bool isOK = true;
741 int16_t res = 0;
742 uint16_t length = arg0;
743 uint16_t pos = 0;
744 uint8_t *fwdata = BigBuf_get_addr();
745 uint8_t *verfiydata = BigBuf_malloc(I2C_BLOCK_SIZE);
746
747 while (length) {
748
749 uint8_t msb = (pos >> 8) & 0xFF;
750 uint8_t lsb = pos & 0xFF;
751
752 Dbprintf("FW %02X%02X", msb, lsb);
753
754 size_t size = MIN(I2C_BLOCK_SIZE, length);
755
756 // write
757 res = I2C_WriteFW(fwdata+pos, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
758 if ( !res ) {
759 DbpString("Writing failed");
760 isOK = false;
761 break;
762 }
763
764 // writing takes time.
765 WaitMS(50);
766
767 // read
768 res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
769 if ( res <= 0) {
770 DbpString("Reading back failed");
771 isOK = false;
772 break;
773 }
774
775 // cmp
776 if ( 0 != memcmp(fwdata+pos, verfiydata, size)) {
777 DbpString("not equal data");
778 isOK = false;
779 break;
780 }
781
782 length -= size;
783 pos += size;
784 }
785 cmd_send(CMD_ACK, isOK, pos, 0, 0, 0);
786 LED_C_OFF();
787 BigBuf_free();
788 }
789
790 // unfinished (or not needed?)
791 //void SmartCardSetBaud(uint64_t arg0) {
792 //}
793
794 void SmartCardSetClock(uint64_t arg0) {
795 LED_D_ON();
796 set_tracing(true);
797 I2C_Reset_EnterMainProgram();
798
799 // Send SIM CLC
800 // start [C0 05 xx] stop
801 I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN);
802
803 cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
804 set_tracing(false);
805 LEDsoff();
806 }
807
808 #endif
Impressum, Datenschutz