Moved C-Netz "Speicherkarte" to "extra" directory and improved it.
This commit is contained in:
12
extra/Makefile.am
Normal file
12
extra/Makefile.am
Normal file
@@ -0,0 +1,12 @@
|
||||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
|
||||
|
||||
bin_PROGRAMS = \
|
||||
cnetz_memory_card_generator
|
||||
|
||||
cnetz_memory_card_generator_SOURCES = \
|
||||
main.c
|
||||
cnetz_memory_card_generator_LDADD = \
|
||||
$(COMMON_LA) \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/liboptions/liboptions.a
|
||||
|
58
extra/README
Normal file
58
extra/README
Normal file
@@ -0,0 +1,58 @@
|
||||
This is a generator for the C-Netz Sim Card
|
||||
"Berechtigungskarte als Speicherkarte". (memory card)
|
||||
|
||||
In the sub directory "simulator" you find an Arduino Sketch to simulate a memory card.
|
||||
|
||||
In the sub directory "programmer" you find an Arduino Sketch to program an SLE4428 card.
|
||||
|
||||
NOTE:
|
||||
This will only work with old phones that were released before the CPU SIM was released.
|
||||
The Smart Card "Berechtigungskarte als Prozessorkarte" is implemented at src/sim.
|
||||
|
||||
|
||||
Run cnetz_memory_card_generator:
|
||||
|
||||
# ./extra/cnetz_memory_card_generator
|
||||
Usage: ./cnetz_memory_card_generator <futln_nat> <futln_fuvst> <futln_rest> <sicherungscode> <sonderheitsschluessel>
|
||||
|
||||
# ./extra/cnetz_memory_card_generator 2222002
|
||||
|
||||
Magic Data 011..015 = 30 (0x1e)
|
||||
Magic Data 018..020 = 7
|
||||
Magic Data 021..023 = 2
|
||||
FUTLN NAT = 2
|
||||
FUTLN FUVST = 2
|
||||
FUTLN REST = 22002
|
||||
Sicherungscode=12345
|
||||
Sonderheitenschluessel=0 (0x0000)
|
||||
Wartungsschluessel=65535 (0xffff)
|
||||
|
||||
Binary data: (LSB first)
|
||||
0xff, 0xf7, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4b, 0x90,
|
||||
0x5f, 0x25, 0x07, 0x0c, 0x00, 0x00, 0xfe, 0xfd,
|
||||
0xfb, 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,
|
||||
|
||||
|
||||
After generation, the hex data can be copied to the data array of programmer/programmer.ino or simulator/simulator.ino
|
||||
|
||||
If you use the programmer, connect an SLE4428 or compatible as inicated at the pin definition of programmer.ino.
|
||||
|
||||
Note: The SLE card must not have protected serial number area. (ATR area)
|
||||
Also the card must show all 416 written bits via ATR, not only 32 bits.
|
||||
|
||||
If you use the Arduino as emulator, connect the card reader as indicated at the pin definition of simulator.ino
|
||||
|
||||
Tested:
|
||||
Works with BSA 51
|
||||
Does not work with all other phones I have.
|
||||
|
||||
Test cards and monitor cards for BSA 51:
|
||||
# ./extra/cnetz_memory_card_generator --special-key 898 2222002
|
||||
# ./extra/cnetz_memory_card_generator --special-key 899 2222002
|
||||
# ./extra/cnetz_memory_card_generator --magic1 0x1d --special-key 0x900 --maintenance-key 0xa139 2222002
|
||||
# ./extra/cnetz_memory_card_generator --magic1 0x1d --special-key 0x901 --maintenance-key 0xa139 2222002
|
||||
|
257
extra/main.c
Normal file
257
extra/main.c
Normal file
@@ -0,0 +1,257 @@
|
||||
/* SIM Card for C-Netz "Berechtigungskarte als Speicherkarte"
|
||||
*
|
||||
* (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <../src/libdebug/debug.h>
|
||||
#include <../src/liboptions/options.h>
|
||||
|
||||
int num_kanal = 1;
|
||||
static uint8_t magic1 = 0x1e;
|
||||
static uint8_t magic2 = 0x7;
|
||||
static uint8_t magic3 = 0x2;
|
||||
static const char *futln;
|
||||
static uint8_t futln_nat;
|
||||
static uint8_t futln_fuvst;
|
||||
static uint16_t futln_rest;
|
||||
static uint16_t sicherungscode = 12345;
|
||||
static uint16_t sonderheitenschluessel = 0;
|
||||
static uint16_t wartungsschluessel = 0xffff;
|
||||
|
||||
/* return 1, if 1-bits are odd, so parity becomes even */
|
||||
static int gen_parity(uint8_t *bits)
|
||||
{
|
||||
int i;
|
||||
uint8_t parity = 0;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
parity ^= (bits[i] & 1);
|
||||
|
||||
return parity;
|
||||
}
|
||||
|
||||
static uint8_t *gen_memory(uint8_t magic1, uint8_t magic2, uint8_t magic3, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, uint16_t sicherungscode, uint16_t sonderheitenschluessel, uint16_t wartungsschluessel)
|
||||
{
|
||||
static uint8_t memory[416];
|
||||
int i;
|
||||
|
||||
/* meaningless data */
|
||||
for (i = 0; i <= 10; i++)
|
||||
memory[i] = 1;
|
||||
|
||||
/* magic data */
|
||||
for (i = 11; i <= 15; i++)
|
||||
memory[i] = (magic1 >> (i - 11)) & 1;
|
||||
|
||||
/* meaningless data */
|
||||
for (i = 16; i <= 17; i++)
|
||||
memory[i] = 0;
|
||||
|
||||
/* magic data */
|
||||
for (i = 18; i <= 20; i++)
|
||||
memory[i] = (magic2 >> (i - 18)) & 1;
|
||||
|
||||
/* magic data */
|
||||
for (i = 21; i <= 23; i++)
|
||||
memory[i] = (magic3 >> (i - 21)) & 1;
|
||||
|
||||
/* meaningless data */
|
||||
for (i = 24; i <= 113; i++)
|
||||
memory[i] = 1;
|
||||
|
||||
/* number */
|
||||
for (i = 114; i <= 116; i++)
|
||||
memory[i] = (futln_nat >> (i - 114)) & 1;
|
||||
for (i = 117; i <= 121; i++)
|
||||
memory[i] = (futln_fuvst >> (i - 117)) & 1;
|
||||
memory[122] = gen_parity(memory + 114);
|
||||
for (i = 123; i <= 130; i++)
|
||||
memory[i] = (futln_rest >> (i - 123)) & 1;
|
||||
memory[131] = gen_parity(memory + 123);
|
||||
for (i = 132; i <= 139; i++)
|
||||
memory[i] = (futln_rest >> (i - 132 + 8)) & 1;
|
||||
memory[140] = gen_parity(memory + 132);
|
||||
|
||||
/* sicherungscode */
|
||||
for (i = 141; i <= 148; i++)
|
||||
memory[i] = (sicherungscode >> (i - 141)) & 1;
|
||||
memory[149] = gen_parity(memory + 141);
|
||||
for (i = 150; i <= 157; i++)
|
||||
memory[i] = (sicherungscode >> (i - 150 + 8)) & 1;
|
||||
memory[158] = gen_parity(memory + 150);
|
||||
|
||||
/* sonderheitenschluessel */
|
||||
for (i = 159; i <= 166; i++)
|
||||
memory[i] = (sonderheitenschluessel >> (i - 159)) & 1;
|
||||
memory[167] = gen_parity(memory + 159);
|
||||
for (i = 168; i <= 175; i++)
|
||||
memory[i] = (sonderheitenschluessel >> (i - 168 + 8)) & 1;
|
||||
memory[176] = gen_parity(memory + 168);
|
||||
|
||||
/* wartungschluessel */
|
||||
for (i = 177; i <= 184; i++)
|
||||
memory[i] = (wartungsschluessel >> (i - 177)) & 1;
|
||||
memory[185] = gen_parity(memory + 177);
|
||||
for (i = 186; i <= 193; i++)
|
||||
memory[i] = (wartungsschluessel >> (i - 186 + 8)) & 1;
|
||||
memory[194] = gen_parity(memory + 186);
|
||||
|
||||
/* meaningless data */
|
||||
for (i = 195; i <= 351; i++)
|
||||
memory[i] = 1;
|
||||
|
||||
/* all zero */
|
||||
for (i = 352; i <= 415; i++)
|
||||
memory[i] = 0;
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
printf("Usage: %s [options] <subscriber number>\n", arg0);
|
||||
/* - - */
|
||||
printf("General options:\n");
|
||||
printf(" -h --help\n");
|
||||
printf(" This help\n");
|
||||
printf(" -1 --magic1 <value>\n");
|
||||
printf(" Magic value for bits 011-015 (default = 0x%02x)\n", magic1);
|
||||
printf(" -2 --magic2 <value>\n");
|
||||
printf(" Magic value for bits 018-021 (default = 0x%x)\n", magic2);
|
||||
printf(" -3 --magic3 <value>\n");
|
||||
printf(" Magic value for bits 022-024 (default = 0x%x)\n", magic3);
|
||||
printf(" -C --security-code \n");
|
||||
printf(" Security code (\"Sicherungscode\") (default = %d)\n", sicherungscode);
|
||||
printf(" -S --special-key \n");
|
||||
printf(" Special key (\"Sonderheitenschluessel\") (default = %d)\n", sonderheitenschluessel);
|
||||
printf(" -W --maintenance-key \n");
|
||||
printf(" Maintenance key (\"Wartungsschluessel\") (default = %d)\n", wartungsschluessel);
|
||||
printf("\nSubscriber number:\n");
|
||||
printf(" Give 7 (8) digits of C-Netz subscriber number (FUTLN) without prefix.\n");
|
||||
}
|
||||
|
||||
void add_options(void)
|
||||
{
|
||||
option_add('h', "help", 0);
|
||||
option_add('1', "magic1", 1);
|
||||
option_add('2', "magic2", 2);
|
||||
option_add('3', "magic3", 3);
|
||||
option_add('C', "security-code", 1);
|
||||
option_add('S', "special-key", 1);
|
||||
option_add('W', "maintenance-key", 1);
|
||||
};
|
||||
|
||||
int handle_options(int short_option, int argi, char **argv)
|
||||
{
|
||||
switch (short_option) {
|
||||
case 'h':
|
||||
print_help(argv[0]);
|
||||
return 0;
|
||||
case '1':
|
||||
magic1 = strtoul(argv[argi], NULL, 0);
|
||||
break;
|
||||
case '2':
|
||||
magic2 = strtoul(argv[argi], NULL, 0);
|
||||
break;
|
||||
case '3':
|
||||
magic3 = strtoul(argv[argi], NULL, 0);
|
||||
break;
|
||||
case 'C':
|
||||
sicherungscode = strtoul(argv[argi], NULL, 0);
|
||||
break;
|
||||
case 'S':
|
||||
sonderheitenschluessel = strtoul(argv[argi], NULL, 0);
|
||||
break;
|
||||
case 'W':
|
||||
wartungsschluessel = strtoul(argv[argi], NULL, 0);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int argi;
|
||||
int i;
|
||||
|
||||
debuglevel = DEBUG_INFO;
|
||||
|
||||
add_options();
|
||||
|
||||
/* parse command line */
|
||||
argi = options_command_line(argc, argv, handle_options);
|
||||
if (argi <= 0)
|
||||
return argi;
|
||||
|
||||
/* get subscriber number */
|
||||
if (argi >= argc) {
|
||||
fprintf(stderr, "Expecting subscriber number, use '-h' for help!\n");
|
||||
return 0;
|
||||
}
|
||||
futln = argv[argi];
|
||||
if (strlen(futln) == 7) {
|
||||
futln_nat = *futln++ - '0';
|
||||
futln_fuvst = *futln++ - '0';
|
||||
} else if (strlen(futln) == 8) {
|
||||
futln_nat = *futln++ - '0';
|
||||
futln_fuvst = (*futln++ - '0') * 10;
|
||||
futln_fuvst += *futln++ - '0';
|
||||
} else {
|
||||
inval_sub:
|
||||
fprintf(stderr, "Invalid subscriber number, use '-h' for help!\n");
|
||||
return 0;
|
||||
}
|
||||
futln_rest = (*futln++ - '0') * 10000;
|
||||
futln_rest += (*futln++ - '0') * 1000;
|
||||
futln_rest += (*futln++ - '0') * 100;
|
||||
futln_rest += (*futln++ - '0') * 10;
|
||||
futln_rest += *futln++ - '0';
|
||||
if (futln_nat > 7 || futln_fuvst > 31)
|
||||
goto inval_sub;
|
||||
|
||||
printf("\n");
|
||||
printf("Magic Data 011..015 = %d (0x%02x)\n", magic1, magic1);
|
||||
printf("Magic Data 018..020 = %d\n", magic2);
|
||||
printf("Magic Data 021..023 = %d\n", magic3);
|
||||
printf("FUTLN NAT = %d\n", futln_nat);
|
||||
printf("FUTLN FUVST = %d\n", futln_fuvst);
|
||||
printf("FUTLN REST = %d\n", futln_rest);
|
||||
printf("Sicherungscode=%d\n", sicherungscode);
|
||||
printf("Sonderheitenschluessel=%d (0x%04x)\n", sonderheitenschluessel, sonderheitenschluessel);
|
||||
printf("Wartungsschluessel=%d (0x%04x)\n", wartungsschluessel, wartungsschluessel);
|
||||
printf("\nBinary data: (LSB first)\n");
|
||||
|
||||
uint8_t *bits = gen_memory(magic1, magic2, magic3, futln_nat, futln_fuvst, futln_rest, sicherungscode, sonderheitenschluessel, wartungsschluessel);
|
||||
for (i = 0; i < 52; i++) {
|
||||
printf("0x%02x, ", bits[0] + (bits[1] << 1) + (bits[2] << 2) + (bits[3] << 3) + (bits[4] << 4) + (bits[5] << 5) + (bits[6] << 6) + (bits[7] << 7));
|
||||
bits += 8;
|
||||
if ((i & 7) == 7)
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
231
extra/programmer/programmer.ino
Normal file
231
extra/programmer/programmer.ino
Normal file
@@ -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;
|
||||
}
|
||||
|
126
extra/simulator/simulator.ino
Normal file
126
extra/simulator/simulator.ino
Normal file
@@ -0,0 +1,126 @@
|
||||
/* SIM card for ATMEL
|
||||
*
|
||||
* (C) 2020 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(__AVR_ATtiny85__)
|
||||
#define RST_PIN 2
|
||||
#define CLK_PIN 3
|
||||
#define DATA_PIN 4
|
||||
#error UNTESTED!
|
||||
#else
|
||||
#define CLK_PIN 5
|
||||
#define RST_PIN 6
|
||||
#define DATA_PIN 7
|
||||
#endif
|
||||
|
||||
uint8_t card_data[] = {
|
||||
|
||||
0xff, 0xf7, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4b, 0x90,
|
||||
0x5f, 0x25, 0x07, 0x0c, 0x00, 0x00, 0xfe, 0xfd,
|
||||
0xfb, 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,
|
||||
|
||||
};
|
||||
|
||||
volatile uint8_t *rst_in, *clk_in, *data_in, *data_out, *data_mode;
|
||||
uint8_t rst_bit, clk_bit, data_bit;
|
||||
|
||||
void setup()
|
||||
{
|
||||
volatile uint8_t *out, *mode;
|
||||
uint8_t port;
|
||||
|
||||
rst_bit = digitalPinToBitMask(RST_PIN);
|
||||
port = digitalPinToPort(RST_PIN);
|
||||
mode = portModeRegister(port);
|
||||
out = portOutputRegister(port);
|
||||
rst_in = portInputRegister(port);
|
||||
*mode &= ~rst_bit; /* input */
|
||||
*out |= rst_bit; /* pullup */
|
||||
|
||||
clk_bit = digitalPinToBitMask(CLK_PIN);
|
||||
port = digitalPinToPort(CLK_PIN);
|
||||
mode = portModeRegister(port);
|
||||
out = portOutputRegister(port);
|
||||
clk_in = portInputRegister(port);
|
||||
*mode &= ~clk_bit; /* input */
|
||||
*out |= clk_bit; /* pullup */
|
||||
|
||||
data_bit = digitalPinToBitMask(DATA_PIN);
|
||||
port = digitalPinToPort(DATA_PIN);
|
||||
data_mode = portModeRegister(port);
|
||||
data_out = portOutputRegister(port);
|
||||
data_in = portInputRegister(port);
|
||||
*data_mode |= data_bit; /* output */
|
||||
}
|
||||
|
||||
uint8_t byte_count;
|
||||
uint8_t bit_count;
|
||||
|
||||
void loop()
|
||||
{
|
||||
reset:
|
||||
byte_count = 0;
|
||||
bit_count = 0;
|
||||
|
||||
/* wait for reset pulse */
|
||||
while (!(*rst_in & rst_bit));
|
||||
/* now we have reset, so we wait for clock pulse */
|
||||
while (!(*clk_in & clk_bit)) {
|
||||
/* if we lost reset, go to start */
|
||||
if (!(*rst_in & rst_bit))
|
||||
goto reset;
|
||||
}
|
||||
while ((*clk_in & clk_bit)) {
|
||||
/* if we lost reset, go to start */
|
||||
if (!(*rst_in & rst_bit))
|
||||
goto reset;
|
||||
}
|
||||
while ((*rst_in & rst_bit));
|
||||
|
||||
next_bit:
|
||||
/* present bit */
|
||||
if ((card_data[byte_count] >> bit_count) & 1)
|
||||
*data_out |= data_bit; /* high */
|
||||
else
|
||||
*data_out &= ~data_bit; /* low */
|
||||
if (++bit_count == 8) {
|
||||
bit_count = 0;
|
||||
if (++byte_count == sizeof(card_data)) {
|
||||
goto reset;
|
||||
}
|
||||
}
|
||||
|
||||
/* wait for clock pulse */
|
||||
while (!(*clk_in & clk_bit)) {
|
||||
/* reset counter if reset was detected */
|
||||
if ((*rst_in & rst_bit)) {
|
||||
goto reset;
|
||||
}
|
||||
}
|
||||
while ((*clk_in & clk_bit)) {
|
||||
/* reset counter if reset was detected */
|
||||
if ((*rst_in & rst_bit)) {
|
||||
goto reset;
|
||||
}
|
||||
}
|
||||
goto next_bit;
|
||||
}
|
Reference in New Issue
Block a user