Implementation of "Radiocom 2000", the analog French mobile network
This commit is contained in:
573
src/r2000/frame.c
Normal file
573
src/r2000/frame.c
Normal file
@@ -0,0 +1,573 @@
|
||||
/* Radiocom 2000 frame transcoding
|
||||
*
|
||||
* (C) 2017 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 <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include "../common/hagelbarger.h"
|
||||
#include "../common/debug.h"
|
||||
#include "frame.h"
|
||||
|
||||
static const char *param_hex(uint64_t value)
|
||||
{
|
||||
static char result[32];
|
||||
sprintf(result, "0x%" PRIx64, value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *param_voie_rel(uint64_t value)
|
||||
{
|
||||
return (value) ? "Control Channel" : "Traffic Channel";
|
||||
}
|
||||
|
||||
static const char *param_voie_sm(uint64_t value)
|
||||
{
|
||||
return (value) ? "Traffic Channel" : "Control Channel";
|
||||
}
|
||||
|
||||
const char *param_agi(uint64_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return "Prohibited control channel (no mobile allowed)";
|
||||
case 1:
|
||||
return "New registration prohibited (registered mobiles allowed)";
|
||||
case 2:
|
||||
return "Registration is reserved to test mobiles";
|
||||
case 3:
|
||||
return "Registration for nominal mobiles (home network)";
|
||||
case 4:
|
||||
return "Registration is reserved to special mobiles";
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
return "Registration permissible for all mobile station";
|
||||
}
|
||||
return "<invalid>";
|
||||
}
|
||||
|
||||
const char *param_aga(uint64_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return "Outgoing calls prohibited";
|
||||
case 1:
|
||||
return "Reserved (Outgoing calls prohibited)";
|
||||
case 2:
|
||||
return "Outgoing call reserved for privileged mobiles";
|
||||
case 3:
|
||||
return "Outgoing calls permissible";
|
||||
}
|
||||
return "<invalid>";
|
||||
}
|
||||
|
||||
const char *param_power(uint64_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return "Low";
|
||||
case 1:
|
||||
return "High";
|
||||
}
|
||||
return "<invalid>";
|
||||
}
|
||||
|
||||
const char *param_crins(uint64_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return "Finished or just registering";
|
||||
case 1:
|
||||
return "Localization impossible (queue full)";
|
||||
case 2:
|
||||
return "Mobile station temporarily disabled";
|
||||
case 3:
|
||||
return "Mobile station definitely disabled (WILL BRICK THE PHONE!)";
|
||||
case 4:
|
||||
return "Blocked localization (BS out of order)";
|
||||
case 5:
|
||||
case 6:
|
||||
return "Reserved";
|
||||
case 7:
|
||||
return "Calling subscriber unknown";
|
||||
}
|
||||
return "<invalid>";
|
||||
}
|
||||
|
||||
const char *param_invitation(uint64_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case 3:
|
||||
return "to Answer";
|
||||
case 10:
|
||||
return "to Dial";
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
static const char *param_digit(uint64_t value)
|
||||
{
|
||||
static char result[32];
|
||||
switch (value) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
sprintf(result, "'%c'", (int)value + '0');
|
||||
return result;
|
||||
case 10:
|
||||
return "'*'";
|
||||
case 11:
|
||||
return "'#'";
|
||||
case 12:
|
||||
return "'A'";
|
||||
case 13:
|
||||
return "'B'";
|
||||
case 14:
|
||||
return "'C'";
|
||||
case 15:
|
||||
return "'D'";
|
||||
}
|
||||
return "<invalid>";
|
||||
}
|
||||
|
||||
static struct r2000_element {
|
||||
char element;
|
||||
const char *name;
|
||||
const char *(*decoder_rel)(uint64_t value); /* REL sends to SM */
|
||||
const char *(*decoder_sm)(uint64_t value); /* SM sends to REL */
|
||||
} r2000_element[] = {
|
||||
{ 'V', "Channel Type", param_voie_rel, param_voie_sm },
|
||||
{ 'C', "Channel", NULL, NULL },
|
||||
{ 'R', "Relais", NULL, NULL },
|
||||
{ 'M', "Message", NULL, NULL },
|
||||
{ 'D', "Deport", NULL, NULL },
|
||||
{ 'I', "AGI", param_agi, param_agi },
|
||||
// { 'A', "AGA", param_aga, param_aga },
|
||||
{ 'P', "power", param_power, param_power },
|
||||
{ 'T', "taxe", NULL, NULL },
|
||||
{ 't', "SM Type", param_hex, param_hex },
|
||||
{ 'r', "SM Relais", NULL, NULL },
|
||||
{ 'f', "SM Flotte", NULL, NULL },
|
||||
{ 'm', "SM ID", NULL, NULL },
|
||||
{ 'd', "Called ID", NULL, NULL },
|
||||
{ 'c', "CRINS", param_crins, param_crins },
|
||||
{ 'a', "Assign Channel", NULL, NULL },
|
||||
{ 's', "Sequence Number", param_hex, param_hex },
|
||||
{ 'i', "Invitation", param_invitation,param_invitation },
|
||||
{ 'n', "NCONV", NULL, NULL },
|
||||
{ '0', "1st Digit", param_digit, param_digit },
|
||||
{ '1', "2nd Digit", param_digit, param_digit },
|
||||
{ '2', "3rd Digit", param_digit, param_digit },
|
||||
{ '3', "4th Digit", param_digit, param_digit },
|
||||
{ '4', "5th Digit", param_digit, param_digit },
|
||||
{ '5', "6th Digit", param_digit, param_digit },
|
||||
{ '6', "7th Digit", param_digit, param_digit },
|
||||
{ '7', "8th Digit", param_digit, param_digit },
|
||||
{ '8', "9th Digit", param_digit, param_digit },
|
||||
{ '9', "10th Digit", param_digit, param_digit },
|
||||
{ '?', "Unknown", param_hex, param_hex },
|
||||
{ 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static void print_element(char element, uint64_t value, int dir, int debug)
|
||||
{
|
||||
const char *(*decoder)(uint64_t value);
|
||||
int i;
|
||||
|
||||
for (i = 0; r2000_element[i].element; i++) {
|
||||
if (r2000_element[i].element == element)
|
||||
break;
|
||||
}
|
||||
decoder = (dir == REL_TO_SM) ? r2000_element[i].decoder_rel : r2000_element[i].decoder_sm;
|
||||
|
||||
if (!r2000_element[i].element)
|
||||
PDEBUG(DFRAME, debug, "Element '%c' %" PRIu64 " [Unknown]\n", element, value);
|
||||
else if (!decoder)
|
||||
PDEBUG(DFRAME, debug, "Element '%c' %" PRIu64 " [%s]\n", element, value, r2000_element[i].name);
|
||||
else
|
||||
PDEBUG(DFRAME, debug, "Element '%c' %" PRIu64 "=%s [%s]\n", element, value, decoder(value), r2000_element[i].name);
|
||||
}
|
||||
|
||||
static void store_element(frame_t *frame, char element, uint64_t value)
|
||||
{
|
||||
switch(element) {
|
||||
case 'V':
|
||||
frame->voie = value;
|
||||
break;
|
||||
case 'C':
|
||||
frame->channel = value;
|
||||
break;
|
||||
case 'R':
|
||||
frame->relais = value;
|
||||
break;
|
||||
case 'M':
|
||||
frame->message = value;
|
||||
break;
|
||||
case 'D':
|
||||
frame->deport = value;
|
||||
break;
|
||||
case 'I':
|
||||
frame->agi = value;
|
||||
break;
|
||||
case 'P':
|
||||
frame->sm_power = value;
|
||||
break;
|
||||
case 'T':
|
||||
frame->taxe = value;
|
||||
break;
|
||||
case 't':
|
||||
frame->sm_type = value;
|
||||
break;
|
||||
case 'r':
|
||||
frame->sm_relais = value;
|
||||
break;
|
||||
case 'f':
|
||||
frame->sm_flotte = value;
|
||||
break;
|
||||
case 'm':
|
||||
frame->sm_mor = value;
|
||||
break;
|
||||
case 'd':
|
||||
frame->sm_mop_demandee = value;
|
||||
break;
|
||||
case 'c':
|
||||
frame->crins = value;
|
||||
break;
|
||||
case 'a':
|
||||
frame->chan_assign = value;
|
||||
break;
|
||||
case 's':
|
||||
frame->sequence = value;
|
||||
break;
|
||||
case 'i':
|
||||
frame->invitation = value;
|
||||
break;
|
||||
case 'n':
|
||||
frame->nconv = value;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
frame->digit[element - '0'] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t fetch_element(frame_t *frame, char element)
|
||||
{
|
||||
switch(element) {
|
||||
case 'V':
|
||||
return frame->voie;
|
||||
case 'C':
|
||||
return frame->channel;
|
||||
case 'R':
|
||||
return frame->relais;
|
||||
case 'M':
|
||||
return frame->message;
|
||||
case 'D':
|
||||
return frame->deport;
|
||||
case 'I':
|
||||
return frame->agi;
|
||||
case 'P':
|
||||
return frame->sm_power;
|
||||
case 'T':
|
||||
return frame->taxe;
|
||||
case 't':
|
||||
return frame->sm_type;
|
||||
case 'r':
|
||||
return frame->sm_relais;
|
||||
case 'f':
|
||||
return frame->sm_flotte;
|
||||
case 'm':
|
||||
return frame->sm_mor;
|
||||
case 'd':
|
||||
return frame->sm_mop_demandee;
|
||||
case 'c':
|
||||
return frame->crins;
|
||||
case 'a':
|
||||
return frame->chan_assign;
|
||||
case 's':
|
||||
return frame->sequence;
|
||||
case 'i':
|
||||
return frame->invitation;
|
||||
case 'n':
|
||||
return frame->nconv;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return frame->digit[element - '0'];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct r2000_frame {
|
||||
int dir;
|
||||
uint8_t message;
|
||||
const char *def;
|
||||
const char *name;
|
||||
} r2000_frame_def[] = {
|
||||
/* V Channel-Relais---Msg--t--HomeRel--MobieID--------- Supervisory----- */
|
||||
/* messages REL->SM */
|
||||
{ REL_TO_SM, 0, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm-----ccc----DDDIII++---PT---", "INSCRIPTION ACK" }, /* inscription ack */
|
||||
{ REL_TO_SM, 2, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm------------DDDIII++---PT---", "PLEASE WAIT" }, /* waiting on CC */
|
||||
{ REL_TO_SM, 1, "V-CCCCCCCCRRRRRRRRRMMMMM----------------------------------------DDDIII++---PT---", "IDLE" }, /* broadcast */
|
||||
{ REL_TO_SM, 3, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmmaaaaaaaa----DDDIII++---PT---", "ASSIGN INCOMING"}, /* assign incoming call */
|
||||
{ REL_TO_SM, 4, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrfffffffffmmmmmmmaaaaaaaa----DDDIII++---PT---", "ASSIGN GROUP"}, /* assign groupp call */
|
||||
{ REL_TO_SM, 5, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmmaaaaaaaa----DDDIII++---PT---", "ASSIGN OUTGOING"}, /* assign outgoing call */
|
||||
{ REL_TO_SM, 9, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm------------DDDIII++---PT---", "RELEASE ON CC" }, /* release call on CC */
|
||||
{ REL_TO_SM, 16, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm----------------------------", "IDENTITY REQ"}, /* request identity */
|
||||
{ REL_TO_SM, 17, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm-----nnniiii----------------", "INVITATION"}, /* invitation */
|
||||
{ REL_TO_SM, 24, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm----------------------------", "RELEASE ON TC"}, /* release call */
|
||||
{ REL_TO_SM, 26, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm----------------------------", "SUSPEND REQ"}, /* suspend after dialing */
|
||||
/* messages SM->REL */
|
||||
{ SM_TO_REL, 0, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm--------ssss", "INSCRIPTION REQ" }, /* inscription */
|
||||
{ SM_TO_REL, 1, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm--------ssss", "CALL REQ (PRIVATE)" }, /* request call */
|
||||
{ SM_TO_REL, 1, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrfffffffffmmmmmmmddddddddssss", "CALL REQ (GROUP)" }, /* request call */
|
||||
{ SM_TO_REL, 3, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm--------ssss", "CALL REQ (PUBLIC)" }, /* request call */
|
||||
{ SM_TO_REL, 6, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm------------", "RELEASE ON CC" }, /* release on CC */
|
||||
{ SM_TO_REL, 16, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm--------ssss", "IDENTITY ACK" }, /* identity response */
|
||||
{ SM_TO_REL, 17, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm------------", "ANSWER" }, /* answer */
|
||||
{ SM_TO_REL, 19, "V-CCCCCCCCRRRRRRRRRMMMMM1111000033332222555544447777666699998888", "DIAL 1..10" }, /* first 10 digits */
|
||||
{ SM_TO_REL, 20, "V-CCCCCCCCRRRRRRRRRMMMMM1111000033332222555544447777666699998888", "DIAL 11..20" }, /* second 10 digits */
|
||||
{ SM_TO_REL, 24, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm------------", "RELEASE ON TC" }, /* release call on TC */
|
||||
{ SM_TO_REL, 26, "V-CCCCCCCCRRRRRRRRRMMMMMtttrrrrrrrrrmmmmmmmmmmmmmmmm------------", "SUSPEND ACK" }, /* release after dialing */
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const char *get_frame_def(uint8_t message, int dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; r2000_frame_def[i].def; i++) {
|
||||
if (r2000_frame_def[i].message == message && r2000_frame_def[i].dir == dir)
|
||||
return r2000_frame_def[i].def;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *r2000_dir_name(int dir)
|
||||
{
|
||||
return (dir == REL_TO_SM) ? "REL->SM" : "SM->REL";
|
||||
}
|
||||
|
||||
const char *r2000_frame_name(int message, int dir)
|
||||
{
|
||||
static char result[32];
|
||||
int i;
|
||||
|
||||
for (i = 0; r2000_frame_def[i].def; i++) {
|
||||
if (r2000_frame_def[i].message == message && r2000_frame_def[i].dir == dir) {
|
||||
sprintf(result, "%s (%d)", r2000_frame_def[i].name, message);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(result, "UNKNOWN (%d)", message);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void display_bits(const char *def, const uint8_t *message, int num, int debug)
|
||||
{
|
||||
char dispbits[num + 1];
|
||||
int i;
|
||||
|
||||
if (debuglevel > debug)
|
||||
return;
|
||||
|
||||
/* display bits */
|
||||
if (def)
|
||||
PDEBUG(DFRAME, debug, "%s\n", def);
|
||||
for (i = 0; i < num; i++) {
|
||||
dispbits[i] = ((message[i / 8] >> (7 - (i & 7))) & 1) + '0';
|
||||
}
|
||||
dispbits[i] = '\0';
|
||||
PDEBUG(DFRAME, debug, "%s\n", dispbits);
|
||||
}
|
||||
|
||||
static int dissassemble_frame(frame_t *frame, const uint8_t *message, int num)
|
||||
{
|
||||
int i;
|
||||
const char *def;
|
||||
uint64_t value;
|
||||
int dir = (num == 80) ? REL_TO_SM : SM_TO_REL;
|
||||
|
||||
memset(frame, 0, sizeof(*frame));
|
||||
|
||||
frame->message = message[2] & 0x1f;
|
||||
def = get_frame_def(frame->message, dir);
|
||||
if (!def) {
|
||||
PDEBUG(DFRAME, DEBUG_NOTICE, "Received unknown message type %d (maybe radio noise)\n", frame->message);
|
||||
display_bits(NULL, message, num, DEBUG_NOTICE);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
PDEBUG(DFRAME, DEBUG_DEBUG, "Decoding frame %s %s\n", r2000_dir_name(dir), r2000_frame_name(frame->message, dir));
|
||||
|
||||
/* dissassemble elements elements */
|
||||
value = 0;
|
||||
for (i = 0; i < num; i++) {
|
||||
value = (value << 1) | ((message[i / 8] >> (7 - (i & 7))) & 1);
|
||||
if (def[i + 1] != def[i]) {
|
||||
if (def[i] != '-') {
|
||||
print_element(def[i], value, dir, DEBUG_DEBUG);
|
||||
store_element(frame, def[i], value);
|
||||
}
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
display_bits(def, message, num, DEBUG_DEBUG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int assemble_frame(frame_t *frame, uint8_t *message, int num, int debug)
|
||||
{
|
||||
int i;
|
||||
const char *def;
|
||||
uint64_t value = 0; // make GCC happy
|
||||
char element;
|
||||
int dir = (num == 80) ? REL_TO_SM : SM_TO_REL;
|
||||
|
||||
def = get_frame_def(frame->message, dir);
|
||||
if (!def) {
|
||||
PDEBUG(DFRAME, DEBUG_ERROR, "Cannot assemble unknown message type %d, please define/fix!\n", frame->message);
|
||||
abort();
|
||||
}
|
||||
memset(message, 0, (num + 7) / 8);
|
||||
|
||||
if (debug)
|
||||
PDEBUG(DFRAME, DEBUG_DEBUG, "Ccoding frame %s %s\n", r2000_dir_name(dir), r2000_frame_name(frame->message, dir));
|
||||
|
||||
/* assemble elements elements */
|
||||
element = 0;
|
||||
for (i = num - 1; i >= 0; i--) {
|
||||
if (element != def[i]) {
|
||||
element = def[i];
|
||||
switch (def[i]) {
|
||||
case '-':
|
||||
value = 0;
|
||||
break;
|
||||
case '+':
|
||||
value = 0xffffffffffffffff;
|
||||
break;
|
||||
default:
|
||||
value = fetch_element(frame, element);
|
||||
}
|
||||
}
|
||||
message[i / 8] |= (value & 1) << (7 - (i & 7));
|
||||
value >>= 1;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
for (i = 0; i < num; i++) {
|
||||
if (def[i + 1] != def[i] && def[i] != '-' && def[i] != '+') {
|
||||
value = fetch_element(frame, def[i]);
|
||||
print_element(def[i], value, dir, DEBUG_DEBUG);
|
||||
}
|
||||
}
|
||||
|
||||
display_bits(def, message, num, DEBUG_DEBUG);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* encode frame to bits
|
||||
*/
|
||||
const char *encode_frame(frame_t *frame, int debug)
|
||||
{
|
||||
uint8_t message[11], code[23];
|
||||
static char bits[32 + 176 + 1];
|
||||
int i;
|
||||
|
||||
assemble_frame(frame, message, 80, debug);
|
||||
|
||||
/* hagelbarger code */
|
||||
hagelbarger_encode(message, code, 88);
|
||||
memcpy(bits, "10101010101010101010111100010010", 32);
|
||||
for (i = 0; i < 176; i++)
|
||||
bits[i + 32] = ((code[i / 8] >> (7 - (i & 7))) & 1) + '0';
|
||||
bits[208] = '\0';
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
//#define GEGENPROBE
|
||||
|
||||
/* decode bits to frame */
|
||||
int decode_frame(frame_t *frame, const char *bits)
|
||||
{
|
||||
uint8_t message[11], code[23];
|
||||
int i, num = strlen(bits);
|
||||
|
||||
#ifdef GEGENPROBE
|
||||
printf("bits as received=%s\n", bits);
|
||||
#endif
|
||||
/* hagelbarger code */
|
||||
memset(code, 0x00, sizeof(code));
|
||||
for (i = 0; i < num; i++)
|
||||
code[i / 8] |= (bits[i] & 1) << (7 - (i & 7));
|
||||
hagelbarger_decode(code, message, num / 2 - 6);
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < num / 2; i++) {
|
||||
printf("%d", (message[i / 8] >> (7 - (i & 7))) & 1);
|
||||
if ((i & 7) == 7)
|
||||
printf(" = 0x%02x\n", message[i / 8]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GEGENPROBE
|
||||
hagelbarger_encode(message, code, num / 2);
|
||||
printf("bits after re-encoding=");
|
||||
for (i = 0; i < num; i++)
|
||||
printf("%d", (code[i / 8] >> (7 - (i & 7))) & 1);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
return dissassemble_frame(frame, message, num / 2 - 8);
|
||||
}
|
||||
|
Reference in New Issue
Block a user