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