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