From 0b6a5d19cbb1a384d27a6c090e03b6e672af0a2e Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 10 May 2020 19:33:27 +0200 Subject: [PATCH] Moved C-Netz "Speicherkarte" to "extra" directory and improved it. --- .gitignore | 2 +- Makefile.am | 2 +- configure.ac | 2 +- extra/Makefile.am | 12 + extra/README | 58 ++++ extra/main.c | 257 ++++++++++++++++++ .../programmer/programmer.ino | 0 extra/simulator/simulator.ino | 126 +++++++++ sim/Makefile.am | 10 - sim/README | 15 - sim/sim.c | 144 ---------- 11 files changed, 456 insertions(+), 172 deletions(-) create mode 100644 extra/Makefile.am create mode 100644 extra/README create mode 100644 extra/main.c rename sim/simcard.ino => extra/programmer/programmer.ino (100%) create mode 100644 extra/simulator/simulator.ino delete mode 100644 sim/Makefile.am delete mode 100644 sim/README delete mode 100644 sim/sim.c diff --git a/.gitignore b/.gitignore index eff76be..d0f0cd0 100644 --- a/.gitignore +++ b/.gitignore @@ -69,7 +69,7 @@ src/tv/osmotv src/radio/osmoradio src/datenklo/datenklo src/zeitansage/zeitansage -sim/cnetz_sim +extra/cnetz_memory_card_generator src/test/test_filter src/test/test_sendevolumenregler src/test/test_compandor diff --git a/Makefile.am b/Makefile.am index 1073c14..18f4894 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src sim +SUBDIRS = src extra diff --git a/configure.ac b/configure.ac index 542a91e..a09e5d6 100644 --- a/configure.ac +++ b/configure.ac @@ -102,7 +102,7 @@ AC_OUTPUT( src/zeitansage/Makefile src/test/Makefile src/Makefile - sim/Makefile + extra/Makefile Makefile) diff --git a/extra/Makefile.am b/extra/Makefile.am new file mode 100644 index 0000000..5cf7c2f --- /dev/null +++ b/extra/Makefile.am @@ -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 + diff --git a/extra/README b/extra/README new file mode 100644 index 0000000..60e06c0 --- /dev/null +++ b/extra/README @@ -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 + +# ./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 + diff --git a/extra/main.c b/extra/main.c new file mode 100644 index 0000000..1a7b0b7 --- /dev/null +++ b/extra/main.c @@ -0,0 +1,257 @@ +/* SIM Card for C-Netz "Berechtigungskarte als Speicherkarte" + * + * (C) 2016 by Andreas Eversberg + * 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 . + */ + +#include +#include +#include +#include +#include +#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] \n", arg0); + /* - - */ + printf("General options:\n"); + printf(" -h --help\n"); + printf(" This help\n"); + printf(" -1 --magic1 \n"); + printf(" Magic value for bits 011-015 (default = 0x%02x)\n", magic1); + printf(" -2 --magic2 \n"); + printf(" Magic value for bits 018-021 (default = 0x%x)\n", magic2); + printf(" -3 --magic3 \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; +} + diff --git a/sim/simcard.ino b/extra/programmer/programmer.ino similarity index 100% rename from sim/simcard.ino rename to extra/programmer/programmer.ino diff --git a/extra/simulator/simulator.ino b/extra/simulator/simulator.ino new file mode 100644 index 0000000..06b3af1 --- /dev/null +++ b/extra/simulator/simulator.ino @@ -0,0 +1,126 @@ +/* SIM card for ATMEL + * + * (C) 2020 by Andreas Eversberg + * 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 . + */ + +#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; +} diff --git a/sim/Makefile.am b/sim/Makefile.am deleted file mode 100644 index b43e85f..0000000 --- a/sim/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) - -bin_PROGRAMS = \ - cnetz_sim - -cnetz_sim_SOURCES = \ - sim.c -cnetz_sim_LDADD = \ - $(COMMON_LA) - diff --git a/sim/README b/sim/README deleted file mode 100644 index adbae3b..0000000 --- a/sim/README +++ /dev/null @@ -1,15 +0,0 @@ -This is a generator for the C-Netz Sim Card -"Berechtigungskarte als Speicherkarte". - -The Smart Card "Berechtigungskarte als Prozessorkarte" is not supported. - -After generation, the hex data can be copied to the data array of simcard.ino -and written to an SLE4428 or compatible. - -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. - -Tested: -Works with BSA 51 -Does not work with all other phones I have. - diff --git a/sim/sim.c b/sim/sim.c deleted file mode 100644 index 02e9bc6..0000000 --- a/sim/sim.c +++ /dev/null @@ -1,144 +0,0 @@ -/* SIM Card for C-Netz "Berechtigungskarte als Speicherkarte" - * - * (C) 2016 by Andreas Eversberg - * 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 . - */ - -#include -#include -#include - -/* 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 futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, uint16_t sicherungscode, uint16_t sonderheitsschluessel) -{ - static uint8_t memory[416]; - int i; - - /* meaningless data */ - for (i = 0; i <= 10; i++) - memory[i] = 1; - - /* magic data */ - memory[11] = 0; - memory[12] = 1; - memory[13] = 1; - memory[14] = 1; - memory[15] = 1; - - /* meaningless data */ - for (i = 16; i <= 17; i++) - memory[i] = 0; - - /* magic data */ - memory[18] = 1; - memory[19] = 1; - memory[20] = 1; - - /* magic data */ - memory[21] = 0; - memory[22] = 1; - memory[23] = 0; - - /* 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); - - /* sonderheitsschluessel */ - for (i = 159; i <= 166; i++) - memory[i] = (sonderheitsschluessel >> (i - 159)) & 1; - memory[167] = gen_parity(memory + 159); - for (i = 168; i <= 175; i++) - memory[i] = (sonderheitsschluessel >> (i - 168 + 8)) & 1; - memory[176] = gen_parity(memory + 168); - - /* meaningless data */ - for (i = 177; i <= 351; i++) - memory[i] = 1; - - /* all zero */ - for (i = 352; i <= 415; i++) - memory[i] = 0; - - return memory; -} - -int main(int argc, char *argv[]) -{ - - if (argc <= 5) { - printf("Usage: %s \n", argv[0]); - return 0; - } - int i; - uint8_t futln_nat = atoi(argv[1]); - uint8_t futln_fuvst = atoi(argv[2]); - uint16_t futln_rest = atoi(argv[3]); - uint16_t sicherungscode = atoi(argv[4]); - uint16_t sonderheitsschluessel = atoi(argv[5]); - printf("nat=%d\n", futln_nat); - printf("fufvt=%d\n", futln_fuvst); - printf("rest=%d\n", futln_rest); - printf("sicherungscode=%d\n", sicherungscode); - printf("sonderheitsschluessel=%d\n", sonderheitsschluessel); - - printf("Telefonnummer: %d%d%05d\n", futln_nat, futln_fuvst, futln_rest); - - uint8_t *bits = gen_memory(futln_nat, futln_fuvst, futln_rest, sicherungscode, sonderheitsschluessel); - for (i = 0; i < 52; i++) { -//printf("%d %d %d %d %d %d %d %d\n", bits[0], bits[1], bits[2] ,bits[3] ,bits[4] ,bits[5] ,bits[6] ,bits[7]); - 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)); -//printf("\n"); - bits += 8; - if ((i & 7) == 7) - printf("\n"); - } - printf("\n"); - - return 0; -} -