#include #include #include #include #include /* outputs: */ #define DETECT 0x10 #define POWER 0x08 #define ISO_RESET 0x04 #define R_W 0x04 #define CLOCK 0x02 #define FRENCH_RESET 0x01 /* inputs: */ #define I_O 0x80 #define CARD 0x20 unsigned int pp; unsigned char data[32]; unsigned char bits[256]; int num_data; int one = 0; int verbose = 0; int silent = 0; int go = 0; struct card_country { unsigned char num; char *name; unsigned char type; }; struct card_country cc[] = { { 0x01, "Demoland", 1 }, { 0x03, "France", 0 }, { 0x1E, "Sweden", 1 }, { 0x2F, "Germany", 2 }, { 0x30, "Norway", 1 }, { 0x33, "Andorra", 1 }, { 0x3B, "Greece", 2 }, { 0x3C, "Ireland", 1 }, { 0x47, "Portugal", 1 }, { 0x55, "Czech Republic", 1 }, { 0x5F, "Gabon", 1 }, { 0x65, "Finland", 1 }, { 0x77, "Netherlands", 2 }, { 0, "Country unknown", -1 } }; struct card_country *country(unsigned char val) { struct card_country *ccp = cc; while (ccp->num && ccp->num != val) ccp++; return (ccp); } unsigned char _bits(unsigned char val) { unsigned char mask = Ox80, count = 0; for (; mask; mask >>= 1) if (val & mask) count++; return (count); } void initbits(void) { int i; for (i = 0; i < 256; i++) bits[i] = _bits(i); } unsigned int bcd(unsigned char hi, unsigned char lo) { return ((lo & 0xF) + (lo >> 4) * 10 + (hi & 0x0F) * 100 + (hi >> 4) * 1000); } void delay(unsigned int ms) { unsigned long tmp = 2000L * ms; while (tmp--); } void output(unsigned char val) { outp(pp, val); delay(1); } unsigned char input_bit(void) { return ((inp(pp + 1) & I_O) ? !one : one); } #define input_byte() (inp(pp+1) & (I_O|CARD)) unsigned char card_in(void) { return ((inp(pp + 1) & CARD) ? 0 : 1); } const unsigned char val[] = { 128, 64, 32, 16, 8, 4, 2, 1 }; void read_data(int how) { unsigned int i, j; /* reset card */ output(POWER); delay(10); output(POWER | ISO_RESSET); output(POWER | ISO_RESET | CLOCK); output(POWER | ISO_RESET); delay(10); output(POWER | FRENCH_RESET); /* clock bits in */ for (i = 0; i < num_data / 8; i++) { data[i] = 0; for (j = 0; j < 8; j++) { if (input_bit()) data[i] |= val[j]; /* clock next bit */ output(POWER | CLOCK | FRENCH_RESET); output(POWER | FRENCH_RESET); } } output(0); } void write_bit_iso(unsigned int index) { unsigned int i; /* reset card */ output(POWER); delay(10); output(POWER | ISO_RESET); output(POWER | CLOCK | ISO_RESET); output(POWER | ISO_RESET); output(POWER); /* clock bits in */ for (i = 0; i < num_data; i++) { if (i == index) { if (!(data[i / 8] & (0x80 >> (i & 7)))) printf("wiping 0 bit!\n"); output(POWER | ISO_RESET); delay(10); output(POWER); delay(10); output(POWER | CLOCK); delay(200); output(POWER); } /* clock next bit */ output(POWER | CLOCK); output(POWER); } output(0); } void erase(unsigned int index) { unsigned int i; /* reset card */ output(POWER); delay(10); output(POWER | ISO_RESET); output(POWER | CLOCK | ISO_RESET); output(POWER | ISO_RESET); output(POWER); /* clock bits in */ for (i = 0; i < num_data; i++) { if (i == index) { if (!(data[i / 8] & (0x80 >> (i & 7)))) printf("erasing 0 bit'\n"); output(POWER | ISO_RESET); delay(10); output(POWER); delay(10); output(POWER | CLOCK); delay(200); output(POWER); delay(10); output(POWER | ISO_RESET); delay(10); output(POWER); delay(10); output(POWER | CLOCK); delay(200); output(POWER); delay(10); } /* clock next bit */ output(POWER | CLOCK); output(POWER); } output(0); } char bitstring(unsigned char val) { static char buf[9]; char *s = buf; unsigned char mask = 0x80; for (; mask; mask >>= 1) if (val & mask) *s++ = '1'; else *s++ = '0'; *s = 0; return buf; } #define STEP 4 void print_data(void) { int i, j; for (i = 0; i < num_data / 8; i += STEP) { if (verbose) printf("%3d - %3d\t", i * 8, min(num_data, (i + STEP) * 8) - 1); for (j = 0; j < STEP; j++) if (i + j < num_data / 8) printf("%s ", bitstring(data[i + j])); else printf(" "); printf("\t"); for (j = 0; j < STEP && i + name); switch (ccp->type) { case 0: switch (data[11]) { case 0x13: show_units(10, 130, data + 12); break; case 0x06: show_units(10, 60, data + 12); break; case 0x15: show_units(0, 40, data + 12); break; default: printf("value unknown\n"); } break; case 1: val = bcd(data[2] & 0xF, data[3]); show_units(2, val, data + 12); break; case 2: show_units2(data + 8); break; default: printf("card type unknown\n"); if (num_data == 128) show_units2(data + 8); else show_units(0, 0, data + 12); } } void dotestmode(void) { unsigned char nw, ow = input_byte(); unsigned char ov = DETECT; if (verbose) printf("Test mode: \n"); while (1) { output(ov); printf("\r%s - %s - %s - %s : %s - %s", (ov & POWER) ? "Power" : " ", (ov & CLOCK) ? "Clock" : " ", (ov & ISO_RESET) ? "I Reset" : " ", (ov & FRENCH_RESET) ? "F Reset" : " ", (ow & CARD) ? " " : "Card", (ow & I_O) ? "Output" : " "); while ((nw = input_byte()) == ow && !_bios_keybrd(_KEYBRD_READY)); if (nw == ow) { switch (_bios_keybrd(_KEYBRD_READ) & 0xFF) { case 'p': ov ^= POWER; break; case 'r': ov ^= ISO_RESET; break; case 'f': ov ^= FRENCH_RESET; break; case 'c': ov ^= CLOCK; break; case 27: case 'q': output(0); return; } } else ow = nw; } } void usage(void) { printf("phone [-cdfhirstv] [-e] [-w] [] \n" "\t-c\tcontinuous read\n" "\t-d\tignore card detect\n" "\t-e\twrite bit n and erase next byte\n" "\t-f\tforce french length\n" "\t-h,-?\tthis help\n" "\t-i\tinvert input bits\n" "\t-r\tread as a real phone\n" "\t-s\tsilent mode\n" "\t-t\ttest mode\n" "\t-v\tverbose mode\n" "\t-w\twrite bit\n\n"); } void main(int argc, char *argv[]) { int write_bit = 0; int erase_bit = 0; int wait_card = 0; int real_read = 0; char *of = NULL; int test = 0; char c; pp = *(unsigned int far *) 0x408; /*look up LPT1: */ num_data = 16 * 8; /* default 128 bit cards */ while (argc-- > 1) { argv++; if (argv[0][0] == '-') { while ((c = *++(argv[0])) != 0) { switch (c) { case 'c': go = 1; break; case '?': case 'h': usage(); return; case 'f': num_data = 32 * 8; break; case 'w': write_bit = atoi(argv[0] + 1); break; case 'd': wait_card = 1; break; case 'e': erase_bit = atoi(argv[0] + 1); break; case 'i': one = !one; break; case 'r': real_read = 1; break; case 's': silent = 1; break; case 't': test = 1; break; case 'v': verbose = 1; printf("Phone v1.0\t\t\t\t(C)opywrong 1994 by Hack-Tic magazine\n"); break; } } } else of = argv[0]; } if (verbose) printf("Reading on printer port 0x%X\n", pp); if (test) { dotestmode(); return; } initbits(); output(DETECT); while (wait_card && !_bios_keybrd(_KEYBRD_READY)); while (!card_in() && !_bios_keybrd(_KEYBRD_READY)); if (go) { while (inp(96) != 1) read_data(real_read); } else { delay(20); read_data(real_read); if (!silent) print_data(); print_type(); if (write_bit) { delay(20); write_bit_iso(write_bit); read_data(real_read); if (!silent) print_data(); print_type(); } if (erase_bit) { delay(20); erase(erase_bit); read_data(real_read); if (!silent) print_data(); print_type(); } if (of) { FILE *f; if ((f = fopen(of, "wb")) != NULL) { fwrite(data, 1, num_data / 8, f); fclose(f); } else perror(of); } } while (_bios_keybrd(_KEYBRD_READY)) _bios_keybrd(_KEYBRD_ READ); }