diff options
Diffstat (limited to 'extra/programmer/programmer.ino')
-rw-r--r-- | extra/programmer/programmer.ino | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/extra/programmer/programmer.ino b/extra/programmer/programmer.ino new file mode 100644 index 0000000..0bb01d6 --- /dev/null +++ b/extra/programmer/programmer.ino @@ -0,0 +1,231 @@ + +#define RST 8 +#define CLK 9 +#define DATA 10 + +#define PSC1 0xff +#define PSC2 0xff + +uint8_t card_data[] = { + +0xff, 0xf7, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x38, +0x78, 0x28, 0x07, 0x8c, 0xc1, 0x03, 0xfe, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, + +}; + +void setup() +{ + digitalWrite(RST, LOW); + pinMode(RST, OUTPUT); + digitalWrite(CLK, LOW); + pinMode(CLK, OUTPUT); + pinMode(DATA, INPUT_PULLUP); + digitalWrite(DATA, HIGH); + + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + Serial.readStringUntil('\m'); +} + +void loop() +{ +again: + Serial.println("Press 'a' for ATR, 'r' to read card, 'w' to program card, 'u' to unlock card"); + Serial.println("-> You must read card ('r') before you are able to write to card."); + while (42) { + if (Serial.available() == 0) + continue; + char inChar = Serial.read(); + if (inChar == 'a') { + Serial.println("ATR..."); + card_atr(52); + goto again; + } else if (inChar == 'r') { + Serial.println("reading..."); + card_read(52, 0); + goto again; + } else if (inChar == 'w') { + Serial.println("writing..."); + card_write(card_data, sizeof(card_data), 0); + goto again; + } else if (inChar == 'u') { + Serial.println("unlocking..."); + card_unlock(PSC1, PSC2); + goto again; + } else { + goto again; + } + } +} + +void card_atr(int num) +{ + uint8_t data[num]; + + digitalWrite(RST, HIGH); + delayMicroseconds(100); + digitalWrite(CLK, HIGH); + delayMicroseconds(100); + digitalWrite(CLK, LOW); + delayMicroseconds(100); + digitalWrite(RST, LOW); + delayMicroseconds(100); + card_read_bytes(data, num); +} + +void card_read(int num, int address) +{ + uint8_t data[num]; + + card_command(((address >> 2) & 0xc0) | 0x0e, address & 0xff, 0); + digitalWrite(CLK, HIGH); + delayMicroseconds(100); + digitalWrite(CLK, LOW); + delayMicroseconds(100); + card_read_bytes(data, num); +} + +void card_write(uint8_t *data, int num, int address) +{ + int i, cnt; + + for (i = 0; i < num; i++) { + card_command(((address >> 2) & 0xc0) | 0x33, address & 0xff, *data); + cnt = card_erase_and_write(); + if (cnt <= 2) { + Serial.println("write failed!"); +// break; + } + address++; + data++; + } +} + +void card_unlock(uint8_t psc1, uint8_t psc2) +{ + int i; + uint8_t data[3]; + + // read error counter + card_command(0xce, 253, 0); + digitalWrite(CLK, HIGH); + delayMicroseconds(100); + digitalWrite(CLK, LOW); + delayMicroseconds(100); + Serial.println("3 bytes: error counter mask, first PSC code, second psc code"); + card_read_bytes(data, 3); + // check bit to erase + for (i = 0; i < 8; i++) { + if ((data[0] & (1 << i))) + break; + } + if (i == 8) { + Serial.println("SORRY NO MORE BITS TO ERASE TO UNLOCK, YOUR CARD IS BRICKED!"); + return; + } + data[0] = data[0] - (1 << i); + // ease bit to unlock + card_command(0xf2, 253, data[0]); + card_erase_and_write(); + // unlock + Serial.println("unlock bit has been erased, sending PSC code"); + card_command(0xcd, 254, psc1); + card_erase_and_write(); + card_command(0xcd, 255, psc2); + card_erase_and_write(); + // read error counter mask + card_command(0xce, 253, 0); + digitalWrite(CLK, HIGH); + delayMicroseconds(100); + digitalWrite(CLK, LOW); + delayMicroseconds(100); + Serial.println("checking error counter mask, one bit shall be erased..."); + card_read_bytes(data, 1); + // reset unlock mask + Serial.println("PSC code has been sent, resetting error counter mask"); + card_command(0xf3, 253, 0xff); + card_erase_and_write(); + // read error counter mask + card_command(0xce, 253, 0); + digitalWrite(CLK, HIGH); + delayMicroseconds(100); + digitalWrite(CLK, LOW); + delayMicroseconds(100); + Serial.println("reading: error counter mask, all bits should be reset"); + card_read_bytes(data, 1); +} + +void card_command(uint8_t c1, uint8_t c2, uint8_t c3) +{ + int i, j; + uint8_t c[3]; + + c[0] = c1; + c[1] = c2; + c[2] = c3; + Serial.println("card command:"); + Serial.println(c1); + Serial.println(c2); + Serial.println(c3); + + digitalWrite(RST, HIGH); + delayMicroseconds(100); + pinMode(DATA, OUTPUT); + for (i = 0; i < 3; i++) { + for (j = 0; j < 8; j++) { + digitalWrite(DATA, ((c[i] >> j) & 1) ? HIGH : LOW); + delayMicroseconds(100); + digitalWrite(CLK, HIGH); + delayMicroseconds(100); + digitalWrite(CLK, LOW); + delayMicroseconds(100); + } + } + pinMode(DATA, INPUT_PULLUP); + digitalWrite(DATA, HIGH); + digitalWrite(RST, LOW); + delayMicroseconds(100); +} + +void card_read_bytes(uint8_t *data, int num) { + int i, j; + + for (i = 0; i < num; i++) { + for (j = 0; j < 8; j++) { + data[i] = (data[i] >> 1) | ((digitalRead(DATA) != LOW) ? 128 : 0); + Serial.print((digitalRead(DATA) != LOW) ? '1' : '0'); + digitalWrite(CLK, HIGH); + delayMicroseconds(100); + digitalWrite(CLK, LOW); + delayMicroseconds(100); + } + Serial.print(" 0x"); + Serial.println(data[i], HEX); + } +} + +int card_erase_and_write(void) +{ + int i; + + for (i = 0; i < 203; i++) { + digitalWrite(CLK, HIGH); + delayMicroseconds(100); + digitalWrite(CLK, LOW); + delayMicroseconds(100); +if (0) if (digitalRead(DATA) == LOW) { + Serial.print(" -> write pulses:"); + Serial.println(i); + break; + } + } + return i; +} + |