diff --git a/configure b/configure index 100624a..a94ec57 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for mISDNuser 2.0.2. +# Generated by GNU Autoconf 2.68 for mISDNuser 2.0.5. # # Report bugs to . # @@ -709,8 +709,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='mISDNuser' PACKAGE_TARNAME='misdnuser' -PACKAGE_VERSION='2.0.2' -PACKAGE_STRING='mISDNuser 2.0.2' +PACKAGE_VERSION='2.0.5' +PACKAGE_STRING='mISDNuser 2.0.5' PACKAGE_BUGREPORT='i4ldeveloper@isdn4linux.de' PACKAGE_URL='' @@ -1450,7 +1450,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures mISDNuser 2.0.2 to adapt to many kinds of systems. +\`configure' configures mISDNuser 2.0.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1520,7 +1520,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of mISDNuser 2.0.2:";; + short | recursive ) echo "Configuration of mISDNuser 2.0.5:";; esac cat <<\_ACEOF @@ -1628,7 +1628,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -mISDNuser configure 2.0.2 +mISDNuser configure 2.0.5 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -2424,7 +2424,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by mISDNuser $as_me 2.0.2, which was +It was created by mISDNuser $as_me 2.0.5, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -3244,7 +3244,7 @@ fi # Define the identity of the package. PACKAGE='misdnuser' - VERSION='2.0.2' + VERSION='2.0.5' cat >>confdefs.h <<_ACEOF @@ -16011,7 +16011,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by mISDNuser $as_me 2.0.2, which was +This file was extended by mISDNuser $as_me 2.0.5, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16077,7 +16077,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -mISDNuser config.status 2.0.2 +mISDNuser config.status 2.0.5 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 65f1aec..b529cf8 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.63]) -AC_INIT([mISDNuser], [2.0.2], [i4ldeveloper@isdn4linux.de]) +AC_INIT([mISDNuser], [2.0.5], [i4ldeveloper@isdn4linux.de]) AC_CONFIG_SRCDIR([tools/]) AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/example/testcon.c b/example/testcon.c index 8d18e7c..b8f6242 100644 --- a/example/testcon.c +++ b/example/testcon.c @@ -66,6 +66,9 @@ char *pname; fprintf(stderr," 10 set loop back D permanent\n"); fprintf(stderr," 11 clear all loopbacks\n"); fprintf(stderr," 12 L1 Timer3 value to given -n value (allowed values 5-30)\n"); + fprintf(stderr," 13 L1 Test AIS set)\n"); + fprintf(stderr," 14 L1 Test AIS cleared)\n"); + fprintf(stderr," 15 L1 Test set state machine to given -n value (allowed values 0-7, 7 - auto state enabled)\n"); fprintf(stderr," -n Phonenumber to dial or on -F12 T3 value\n"); fprintf(stderr," -vn Printing debug info level n\n"); fprintf(stderr,"\n"); @@ -80,6 +83,7 @@ typedef struct _devinfo { int bchan; struct sockaddr_mISDN baddr; int nds; + int dproto; int bproto; int used_bchannel; int save; @@ -701,7 +705,7 @@ int do_connection(devinfo_t *di) { if (di->setloopback) return 0; - if (di->func == 12) + if (di->func > 12) return 0; hh = (struct mISDNhead *)buf; if (strlen(di->phonenr)) { @@ -875,6 +879,7 @@ int do_setup(devinfo_t *di) { unsigned char buffer[300]; struct mISDN_ctrl_req creq; + di->dproto = ISDN_P_LAPD_TE; switch (di->func) { case 0: case 5: @@ -914,6 +919,10 @@ int do_setup(devinfo_t *di) { di->setloopback = di->func - 7; break; case 12: + case 13: + case 14: + case 15: + di->dproto = ISDN_P_LAPD_NT; break; default: fprintf(stdout,"unknown program function %d\n", @@ -950,7 +959,7 @@ int do_setup(devinfo_t *di) { close(sk); - di->layer2 = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_TE); + di->layer2 = socket(PF_ISDN, SOCK_DGRAM, di->dproto); if (di->layer2 < 0) { fprintf(stdout, "could not open layer2 socket %s\n", strerror(errno)); return 5; @@ -1026,6 +1035,43 @@ int do_setup(devinfo_t *di) { close(di->layer2); return ret; } + if (di->func == 13) { + creq.op = MISDN_CTRL_L1_AIS_TEST; + creq.channel = 0; + creq.p1 = 1; + ret = ioctl(di->layer2, IMCTRLREQ, &creq); + if (ret < 0) + fprintf(stdout,"AIS ioctl error %s\n", strerror(errno)); + else + fprintf(stdout,"AIS ioctl enable successful\n"); + close(di->layer2); + return ret; + } + if (di->func == 14) { + creq.op = MISDN_CTRL_L1_AIS_TEST; + creq.channel = 0; + creq.p1 = 0; + ret = ioctl(di->layer2, IMCTRLREQ, &creq); + if (ret < 0) + fprintf(stdout,"AIS ioctl error %s\n", strerror(errno)); + else + fprintf(stdout,"AIS ioctl disable successful\n"); + close(di->layer2); + return ret; + } + if (di->func == 15) { + creq.op = MISDN_CTRL_L1_STATE_TEST; + creq.channel = 0; + creq.p1 = atol(di->phonenr); + ret = ioctl(di->layer2, IMCTRLREQ, &creq); + if (ret < 0) + fprintf(stdout,"L1 state set ioctl error %s\n", strerror(errno)); + else + fprintf(stdout,"L1 set state(%ld) ioctl successful\n", atol(di->phonenr)); + close(di->layer2); + return ret; + } + hh = (struct mISDNhead *)buffer; while (1) { diff --git a/include/mISDN/mISDNif.h b/include/mISDN/mISDNif.h index b58f629..674a233 100644 --- a/include/mISDN/mISDNif.h +++ b/include/mISDN/mISDNif.h @@ -38,7 +38,7 @@ */ #define MISDN_MAJOR_VERSION 1 #define MISDN_MINOR_VERSION 1 -#define MISDN_RELEASE 27 +#define MISDN_RELEASE 29 /* primitives for information exchange * generell format @@ -362,31 +362,36 @@ clear_channelmap(u_int nr, u_char *map) } /* CONTROL_CHANNEL parameters */ -#define MISDN_CTRL_GETOP 0x0000 -#define MISDN_CTRL_LOOP 0x0001 -#define MISDN_CTRL_CONNECT 0x0002 -#define MISDN_CTRL_DISCONNECT 0x0004 -#define MISDN_CTRL_GET_PCM_SLOTS 0x0010 -#define MISDN_CTRL_SET_PCM_SLOTS 0x0020 -#define MISDN_CTRL_SETPEER 0x0040 -#define MISDN_CTRL_UNSETPEER 0x0080 -#define MISDN_CTRL_RX_OFF 0x0100 -#define MISDN_CTRL_FILL_EMPTY 0x0200 -#define MISDN_CTRL_GETPEER 0x0400 -#define MISDN_CTRL_L1_TIMER3 0x0800 -#define MISDN_CTRL_HW_FEATURES_OP 0x2000 -#define MISDN_CTRL_HW_FEATURES 0x2001 -#define MISDN_CTRL_HFC_OP 0x4000 -#define MISDN_CTRL_HFC_PCM_CONN 0x4001 -#define MISDN_CTRL_HFC_PCM_DISC 0x4002 -#define MISDN_CTRL_HFC_CONF_JOIN 0x4003 -#define MISDN_CTRL_HFC_CONF_SPLIT 0x4004 -#define MISDN_CTRL_HFC_RECEIVE_OFF 0x4005 -#define MISDN_CTRL_HFC_RECEIVE_ON 0x4006 -#define MISDN_CTRL_HFC_ECHOCAN_ON 0x4007 -#define MISDN_CTRL_HFC_ECHOCAN_OFF 0x4008 -#define MISDN_CTRL_HFC_WD_INIT 0x4009 -#define MISDN_CTRL_HFC_WD_RESET 0x400A +#define MISDN_CTRL_GETOP 0x00000000 +#define MISDN_CTRL_LOOP 0x00000001 +#define MISDN_CTRL_CONNECT 0x00000002 +#define MISDN_CTRL_DISCONNECT 0x00000004 +#define MISDN_CTRL_GET_PCM_SLOTS 0x00000010 +#define MISDN_CTRL_SET_PCM_SLOTS 0x00000020 +#define MISDN_CTRL_SETPEER 0x00000040 +#define MISDN_CTRL_UNSETPEER 0x00000080 +#define MISDN_CTRL_RX_OFF 0x00000100 +#define MISDN_CTRL_FILL_EMPTY 0x00000200 +#define MISDN_CTRL_GETPEER 0x00000400 +#define MISDN_CTRL_L1_TIMER3 0x00000800 +#define MISDN_CTRL_HW_FEATURES_OP 0x00002000 +#define MISDN_CTRL_HW_FEATURES 0x00002001 +#define MISDN_CTRL_HFC_OP 0x00004000 +#define MISDN_CTRL_HFC_PCM_CONN 0x00004001 +#define MISDN_CTRL_HFC_PCM_DISC 0x00004002 +#define MISDN_CTRL_HFC_CONF_JOIN 0x00004003 +#define MISDN_CTRL_HFC_CONF_SPLIT 0x00004004 +#define MISDN_CTRL_HFC_RECEIVE_OFF 0x00004005 +#define MISDN_CTRL_HFC_RECEIVE_ON 0x00004006 +#define MISDN_CTRL_HFC_ECHOCAN_ON 0x00004007 +#define MISDN_CTRL_HFC_ECHOCAN_OFF 0x00004008 +#define MISDN_CTRL_HFC_WD_INIT 0x00004009 +#define MISDN_CTRL_HFC_WD_RESET 0x0000400A +#define MISDN_CTRL_L1_TESTS 0x00010000 +#define MISDN_CTRL_L1_STATE_TEST 0x00010001 +#define MISDN_CTRL_L1_AIS_TEST 0x00010002 +#define MISDN_CTRL_L1_TS0_MODE 0x00010003 +#define MISDN_CTRL_L1_GET_SYNC_INFO 0x00010004 /* special PCM slot numbers */ #define MISDN_PCM_SLOT_DISABLE -1 /* PCM disabled */ diff --git a/lib/suppserv/aoc.c b/lib/suppserv/aoc.c index 61b805c..db8484b 100644 --- a/lib/suppserv/aoc.c +++ b/lib/suppserv/aoc.c @@ -258,6 +258,7 @@ int ParseAOCEChargingUnitInfo(struct asn1_parm *pc, u_char * p, u_char * end, st XSEQUENCE_1(ParseAOCEChargingUnitInfoChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, chu); XSEQUENCE_OPT_1(ParseChargingAssociation, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &chu->chargeAssoc); + return p - beg; } // AOCEBillingId diff --git a/tools/E1test.c b/tools/E1test.c new file mode 100644 index 0000000..a95da0c --- /dev/null +++ b/tools/E1test.c @@ -0,0 +1,2054 @@ +/* + * + * Copyright 2011 Karsten Keil + * + * 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 2 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, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FRAME_SIZE 32 +#define SMFR_SIZE (8 * FRAME_SIZE) +#define MFR_SIZE (2 * SMFR_SIZE) +#define DATA_SIZE_125US 32 +#define DATA_SIZE_1MS (8 * 32) +#define DATA_SIZE_1S (8000 * 32) + + +#define MFR_SYNC_VALUE 0x2c +#define MFR_SYNC_MASK 0xfc +#define MFR_SYNC_BIT 0x01 +#define MFR_SYNC_BITS 8 +#define MFR_SYNC_OFFSET 15 + +#define FR_FAS_VAL 0xd8 +#define FR_FAS_VAL_FAIL 0xc0 +#define FR_FAS_MASK 0xfe + +#define FR_NFAS_B2 0xfa +#define FR_NFAS_B2_FAIL 0xf8 + +enum FrameTypes { + ftNone, + /* send out AIS (all TS 0xff) */ + ftAIS, + /* Basic Frames */ + ftFAS, + ftBIT2, + /* Sub multi frames */ + ftSMFA, + ftSMFB, + /* Multi frames */ + ftMFA, + ftMFB, + /* Frames */ + ftFRAME_A, + ftFRAME_B, + ftFRAME_C, + /* Control items */ + ftCtrl_Start, + ftCtrl_Repeat, + ftCtrl_End, + ftCtrl_Stop +}; + +struct fr_cdesc { + enum FrameTypes type; + uint8_t prop; + uint8_t subcnt; + uint16_t count; +}; + +struct fr_flatdesc { + enum FrameTypes type; /* only basic frame types */ + uint8_t prop; + enum FrameTypes otype; /* original type from generation */ + uint8_t mf_pos; /* 0 - 15 */ + uint32_t pos; + uint8_t *data; +}; + +#define ftPROP_NONE 0x00 +#define ftPROP_FAIL 0x01 /* frame type failure (/FAS or /BIT2) */ +#define ftPROP_CRC4 0x02 /* CRC4 failure in submultiframe */ +#define ftPROP_MFAS 0x04 /* MFAS failure in multiframe */ +#define ftPROP_TS31 0x08 /* simulate BIT2 (FAS in TS 0) and FAS (BIT2 in TS0) in TS 31 */ +#define ftPROP_START 0x10 /* Start test */ +#define ftPROP_AIS 0x80 /* AIS */ + +struct fr_data { + int count; + struct fr_flatdesc *desc; + size_t data_size; + uint8_t *data; +}; + +static struct fr_data *TestData; + +struct fr_cdesc preamble[] = { + {ftAIS, ftPROP_AIS, 1, 16000}, + {ftSMFA, ftPROP_NONE, 8, 1100}, + {ftCtrl_Stop, ftPROP_NONE, 0, 0} +}; + +struct fr_cdesc test0[] = { + {ftSMFA, ftPROP_NONE, 8, 10000}, + {ftCtrl_Stop, ftPROP_NONE, 0, 0} +}; + +struct fr_cdesc test1[] = { + {ftSMFA, ftPROP_NONE, 8, 1500}, + {ftCtrl_Start, ftPROP_START, 0, 0}, + {ftSMFA, ftPROP_NONE, 8, 500}, + {ftSMFB, ftPROP_CRC4, 8, 1}, + {ftSMFA, ftPROP_NONE, 8, 1000}, + {ftSMFB, ftPROP_CRC4, 8, 2}, + {ftSMFA, ftPROP_NONE, 8, 1500}, + {ftSMFB, ftPROP_CRC4, 8, 914}, + {ftSMFA, ftPROP_NONE, 8, 86}, + {ftSMFB, ftPROP_CRC4, 8, 914}, + {ftSMFA, ftPROP_NONE, 8, 2000}, + {ftSMFB, ftPROP_CRC4, 8, 915}, + {ftSMFA, ftPROP_NONE, 8, 85}, + {ftSMFB, ftPROP_CRC4, 8, 915}, + {ftSMFA, ftPROP_NONE, 8, 1500}, + {ftCtrl_Repeat, ftPROP_NONE, 0, 4000}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + {ftCtrl_Stop, ftPROP_NONE, 0, 0} +}; + +struct fr_cdesc test2[] = { + {ftCtrl_Repeat, ftPROP_NONE, 0, 9000}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftCtrl_Start, ftPROP_START, 0, 0}, + + {ftCtrl_Repeat, ftPROP_NONE, 0, 1000}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftCtrl_Repeat, ftPROP_NONE, 0, 20}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftCtrl_Repeat, ftPROP_NONE, 0, 20}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftCtrl_Repeat, ftPROP_NONE, 0, 20}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftCtrl_Repeat, ftPROP_NONE, 0, 20}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + + {ftCtrl_Repeat, ftPROP_NONE, 0, 20}, + {ftBIT2, ftPROP_FAIL, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftCtrl_Repeat, ftPROP_NONE, 0, 20}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftCtrl_Repeat, ftPROP_NONE, 0, 20}, + {ftBIT2, ftPROP_FAIL, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftCtrl_Repeat, ftPROP_NONE, 0, 20}, + {ftBIT2, ftPROP_FAIL, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftBIT2, ftPROP_FAIL, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftCtrl_Repeat, ftPROP_NONE, 0, 20}, + {ftBIT2, ftPROP_FAIL, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftBIT2, ftPROP_FAIL, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftBIT2, ftPROP_FAIL, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftCtrl_Repeat, ftPROP_NONE, 0, 200}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_NONE, 1, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftBIT2,ftPROP_NONE, 1, 1}, + {ftFRAME_B, ftPROP_TS31, 2, 16000}, + {ftFRAME_C, ftPROP_TS31, 2, 6}, + {ftFRAME_B, ftPROP_TS31, 2, 16000}, + + {ftCtrl_Stop, ftPROP_NONE, 0, 0} +}; + +struct fr_cdesc test3[] = { + {ftFRAME_B, ftPROP_TS31, 2, 15000}, + + {ftCtrl_Start, ftPROP_START, 0, 0}, + + {ftFRAME_B, ftPROP_TS31, 2, 1000}, + + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 4}, + {ftMFA, ftPROP_NONE, 16, 1}, + + {ftMFB, ftPROP_NONE, 16, 37}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 251}, + + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftMFB, ftPROP_NONE, 16, 250}, + + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 4}, + + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 2}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 2}, + {ftMFA, ftPROP_NONE, 16, 1}, + + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 2}, + {ftMFA, ftPROP_NONE, 16, 2}, + + {ftCtrl_Repeat, ftPROP_NONE, 0, 500}, + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftCtrl_Stop, ftPROP_NONE, 0, 0} +}; + + +struct fr_cdesc test4[] = { + {ftFRAME_B, ftPROP_TS31, 2, 16000}, + + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 4}, + {ftMFA, ftPROP_NONE, 16, 1}, + + {ftMFB, ftPROP_NONE, 16, 37}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 251}, + + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftFAS, ftPROP_FAIL, 1, 1}, + {ftBIT2, ftPROP_NONE, 1, 1}, + {ftMFB, ftPROP_NONE, 16, 250}, + + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 4}, + + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 2}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 2}, + {ftMFA, ftPROP_NONE, 16, 1}, + + {ftMFA, ftPROP_NONE, 16, 1}, + {ftMFB, ftPROP_NONE, 16, 2}, + {ftMFA, ftPROP_NONE, 16, 2}, + + {ftCtrl_Repeat, ftPROP_NONE, 0, 500}, + {ftMFB, ftPROP_NONE, 16, 1}, + {ftMFA, ftPROP_NONE, 16, 1}, + {ftCtrl_End, ftPROP_NONE, 0, 0}, + + {ftCtrl_Stop, ftPROP_NONE, 0, 0} +}; + + +static uint8_t mfr_sync; +static uint8_t startcnt = MFR_SYNC_BITS; + +static uint8_t *inbuf, *ib_p, *ib_end; +static int ib_size, ib_pos; +static uint8_t *outbuf, *ob_p, *ob_end; +static int ob_size, ob_pos; + + +enum FSyncState { + FSync_None, + FSync_FAS, + FSync_NFAS, + FSync_AIS, + FSync_LOS +}; +enum MFRSyncState { + MFR_State_NotSync, + MFR_State_Sync +}; + + +static enum FSyncState fsync_state = FSync_None; +static enum MFRSyncState mfr_state = MFR_State_NotSync; + +static uint8_t *last_mfrs; + +static int good_mfr, bad_mfr; + + +static int debuglevel = 0; +static int RawReadMode = 0; +static int cardnr = 0; +static char * WriteFileName = NULL; +static int ListMode = 0; +struct fr_cdesc *Test = test0; +static void usage(char *pname) +{ + fprintf(stderr,"Call with %s [options]\n", pname); + fprintf(stderr,"\n"); + fprintf(stderr,"\n Valid options are:\n"); + fprintf(stderr,"\n"); + fprintf(stderr," --help -? Usage ; printout this information\n"); + fprintf(stderr," --card -c use card number # (default 0)\n"); + fprintf(stderr," --flat -f list flat test frame description\n"); + fprintf(stderr," --list -l list test frame description\n"); + fprintf(stderr," --raw -r rawread only mode\n"); + fprintf(stderr," --debug -d debuglevel\n"); + fprintf(stderr," --test -t generate data for test # (default 0)\n"); + fprintf(stderr," --write -w write \n"); + fprintf(stderr,"\n"); + fprintf(stderr,"Tests:\n"); + fprintf(stderr," 0 - 10 seconds normal CRC4 framing\n"); + fprintf(stderr," 1 - TBR4 B.4.2 (table B.1)\n"); + fprintf(stderr," 2 - TBR4 B.5.2 (table B.2)\n"); + fprintf(stderr," 3 - TBR4 B.5.3 (table B.3)\n"); + fprintf(stderr,"\n"); +} + +static int opt_parse(int ac, char *av[]) +{ + int c; + + for (;;) { + int option_index = 0; + static struct option long_options[] = { + {"help", 0, 0, '?'}, + {"card", 1, 0, 'c'}, + {"debug", 1, 0, 'd'}, + {"flat", 0, 0, 'f'}, + {"list", 0, 0, 'l'}, + {"raw", 0, 0, 'r'}, + {"test", 1, 0, 't'}, + {"write", 1, 0, 'w'}, + {0, 0, 0, 0} + }; + + c = getopt_long(ac, av, "?c:d:flrt:w:", long_options, &option_index); + if (c == -1) + break; + switch (c) { + case 0: + fprintf(stderr, "option %s", long_options[option_index].name); + if (optarg) + fprintf(stderr, " with arg %s", optarg); + fprintf(stderr, "\n"); + break; + case 'c': + if (optarg) + cardnr = atoi(optarg); + else { + fprintf(stderr, "option -c but no card number\n"); + return -2; + } + break; + case 'w': + if (optarg) + WriteFileName = strdup(optarg); + else { + fprintf(stderr, "option -w but no filename\n"); + return -2; + } + break; + case 'd': + if (optarg) { + debuglevel = atoi(optarg); + } else { + fprintf(stderr, "option -d but no value for debug level\n"); + return -3; + } + break; + case 'l': + ListMode = 1; + break; + case 'f': + ListMode = 2; + break; + case 'r': + RawReadMode = 1; + break; + case 't': + if (optarg) { + switch(*optarg) { + case '0': + Test = test0; + break; + case '1': + Test = test1; + break; + case '2': + Test = test2; + break; + case '3': + Test = test3; + break; + default: + fprintf(stderr, "Unknown test %s\n", optarg); + return -4; + } + } else { + fprintf(stderr, "option -t but no value for test\n"); + return -3; + } + break; + case '?': + usage(av[0]); + return -1; + } + } + c = ac - optind; + if (c != 0) { + fprintf(stderr, "unknown options: %s\n", av[optind]); + return -2; + } + return 0; +} + + + + +static void printbinary(char *name, uint32_t val, uint8_t bits) +{ + uint32_t m; + + if (bits > 32) + bits = 32; + + printf("%s: ", name); + + m = 1 << (bits -1); + while (m) { + printf("%c", val & m ? '1' : '0'); + m >>= 1; + } +} + +static void printhex(unsigned char *p, uint16_t idx, int len, int head) +{ + int i, j; + + for (i = 1; i <= len; i++) { + printf(" %02x", p[idx++]); + if ((i!=len) && !(i % 4) && (i % 16)) + printf(" "); + if ((i!=len) && !(i % 16)) { + printf("\n"); + for (j = 0; j < head; j++) + printf(" "); + } + } + printf("\n"); +} + +/* table for bit swap */ +uint8_t bitswap_tbl[256]; + +/* table for CRC4 (x^4 + x + 1, Generator poly 0x13) */ +uint8_t crc4_tbl[16] = { 0x0, 0x3, 0x6, 0x5, 0xc, 0xf, 0xa, 0x9, 0xb, 0x8, 0xd, 0xe, 0x7, 0x4, 0x1, 0x2 }; + +void calc_bitswap_table(void) +{ + uint8_t v = 0; + + do { + bitswap_tbl[v] = (((v & 0x01) << 7) | ((v & 0x02) << 5) | ((v & 0x04) << 3) | ((v & 0x08) << 1) | + ((v & 0x10) >> 1) | ((v & 0x20) >> 3) | ((v & 0x40) >> 5) | ((v & 0x80) >> 7)); + v++; + } while (v != 0); +} + +static uint8_t calc_crc4(uint8_t *data, uint16_t start, int len) +{ + uint16_t i, idx = start; + uint8_t b, crc4 = 0; + + for (i = 0; i < len; i++) { + b = bitswap_tbl[data[idx]]; + crc4 ^= ((b >> 4) & 0xf); + crc4 = crc4_tbl[crc4]; + crc4 ^= (b & 0xf); + crc4 = crc4_tbl[crc4]; + idx++; + } + return crc4; +}; + +static uint8_t calc_and_set_crc4_smf(uint8_t *smf, uint8_t crc) +{ + uint16_t i; + uint8_t d, b, crc4 = 0; + + for (i = 0; i < SMFR_SIZE; i++) { + d = smf[i]; + if (!(i % 64)) { /* Cx bit */ + d &= 0xfe; + b = bitswap_tbl[d]; + if (crc != 0xff) { /* no set if ff */ + if (crc & 8) + d |= 1; + crc <<= 1; + smf[i] = d; + } + } else + b = bitswap_tbl[d]; + crc4 ^= ((b >> 4) & 0xf); + crc4 = crc4_tbl[crc4]; + crc4 ^= (b & 0xf); + crc4 = crc4_tbl[crc4]; + } + return crc4 & 0xf; +} + +#ifdef NOT_USED_YET +static uint8_t get_crc4_smf(uint8_t *smf) +{ + uint16_t i; + uint8_t crc4 = 0; + + for (i = 0; i < 4; i++) { + crc4 <<= 1; + crc4 |= (smf[64 * i] & 1); + } + return crc4; +} +#endif + +static int cur_Err = 0;// cur_RAI = 0; +static int analyse_mfr(uint8_t *p) +{ + uint16_t i, t0idx; + uint8_t d, crcfr[16]; + uint8_t A = 0; + uint8_t E = 0; + uint8_t C = 0; + uint8_t cr0, cr1; + const char *stim; + struct fr_flatdesc *dsc; + + size_t ipos; + + ob_pos = ob_p - outbuf; + ipos = p - inbuf; + if (ipos < ((MFR_SYNC_OFFSET + 12) * FRAME_SIZE)) { + stim = "VOID"; + } else { + ipos -= ((MFR_SYNC_OFFSET + 12) * FRAME_SIZE); + ipos /= FRAME_SIZE; + dsc = &TestData->desc[ipos]; + switch (dsc->otype) { + case ftAIS: + stim = "AIS"; + break; + /* Basic Frames */ + case ftFAS: + if (dsc->prop & ftPROP_FAIL) + stim = "/FAS"; + else + stim = "FAS"; + break; + case ftBIT2: + if (dsc->prop & ftPROP_FAIL) + stim = "/BIT 2"; + else + stim = "BIT 2"; + break; + /* Sub multi frames */ + case ftSMFA: + stim = "SMF A"; + break; + case ftSMFB: + stim = "SMF B"; + break; + /* Multi frames */ + case ftMFA: + stim = "MF A"; + break; + case ftMFB: + stim = "MF B"; + break; + /* Frames */ + case ftFRAME_A: + stim = "FRAME A"; + break; + case ftFRAME_B: + stim = "FRAME B"; + break; + case ftFRAME_C: + stim = "FRAME C"; + break; + default: + stim = "VOID"; + break; + } + } + + printf("Time:%6d ms {TX: %-7s} MFR %5d Error %3d ", ob_pos/DATA_SIZE_1MS, stim, good_mfr, bad_mfr); + last_mfrs = p; + p -= MFR_SYNC_OFFSET * FRAME_SIZE; + for (i = 0; i < 16; i++) { + t0idx = i * 32; + d = p[t0idx]; + crcfr[i] = d; + if (i & 1) { + A <<= 1; + if (d & 0x04) + A |= 1; + if (i >= 13) { + E <<= 1; + if (d & 0x01) + E |= 1; + } + } else { + C <<= 1; + C |= ( 0x1 & d); + } + } + cr0 = calc_and_set_crc4_smf(p, 0xff); + cr1 = calc_and_set_crc4_smf(p + 256, 0xff); + + switch (E) { + case 0: + cur_Err += 2; + break; + case 1: + cur_Err++; + break; + case 2: + cur_Err = 1; + break; + case 3: + cur_Err = 0; + break; + } + printbinary("A", A, 8); + printbinary(" C", C, 8); + printbinary(" CR0", cr0, 4); + printbinary(" CR1", cr1, 4); + printbinary(" E", E, 2); + printf(" Cerr %4d", cur_Err); + printf(" "); + printhex(crcfr, 0, 16, 0); + if (E == 1) + cur_Err = 0; + return 0; +} + + +/* + * Write one multiframe 16 * 2048 bit ; 512 bytes + * returns the CRC4 for the next sub multiframe + */ +uint8_t fill_outframe(uint8_t *of, uint8_t A, uint8_t E, uint8_t S, uint8_t F, uint8_t cr0, uint8_t MFRSW, uint8_t *dch, uint8_t def) +{ + uint16_t i, tidx; + static unsigned char p; + uint8_t c0, c1, j; + + tidx = 0; + for (i = 0; i < 16; i++) { + if (i & 1) { /* NFAS */ + p = 0xf8 & S; + if (A & 0x80) + p |= 4; + A <<= 1; + p |= 2; + if (i >= 13) { + if (E & 0x2) + p |= 1; + E <<= 1; + } else { + if (MFRSW & 0x80) + p |= 1; + MFRSW <<= 1; + } + } else { + p = F & 0xfe; + } + of[tidx] = p; + tidx++; + for (j = 1; j < 32; j++) { + if (j == 16) { /* D channel */ + of[tidx] = *dch; + dch++; + } else + of[tidx] = def; + tidx++; + } + } + c0 = calc_crc4(of, 0, 256); + c1 = calc_crc4(of, 256, 256); + for (i = 0; i < 16; i += 2) { + tidx = 32 * i; + p = of[tidx]; + if (i < 8) { + if (cr0 & 0x8) + p |= 1; + cr0 <<= 1; + } else { + if (c0 & 0x8) + p |= 1; + c0 <<= 1; + } + of[tidx] = p; + } + return c1; +} + +static uint8_t *ib_cp; + +static int process_data(int cnt) +{ + uint16_t dist, nidx; + uint8_t i; + static uint8_t fr[5]; + static enum FSyncState frT[5]; + + if (debuglevel == 2) + printf("Start %d %p/%p ", cnt, ib_cp, ib_p); + while (1) { + dist = ib_p - ib_cp; + if (dist <= 400) + break; + switch (fsync_state) { + case FSync_None: + case FSync_AIS: + case FSync_LOS: + /* hunt for basic sync */ + fr[0] = ib_cp[0]; + if ((fr[0] & FR_FAS_MASK) != FR_FAS_VAL) { + ib_cp++; + continue; + } else { + frT[0] = FSync_FAS; + if (debuglevel == 2) + printf("F"); + nidx = 32; + fr[1] = ib_cp[nidx]; + if (!(fr[1] & 0x2)) { + ib_cp++; + continue; + } else + frT[1] = FSync_NFAS; + if (debuglevel == 2) + printf("N"); + nidx = 64; + fr[2] = ib_cp[nidx]; + if ((fr[2] & FR_FAS_MASK) != FR_FAS_VAL) { + ib_cp++; + continue; + } else + frT[2] = FSync_FAS; + if (debuglevel == 2) + printf("f %p/%d", ib_cp, dist); + for (i = 3; i < 5; i++) { + nidx = i * 32; + fr[i] = ib_cp[nidx]; + if ((fr[i] & FR_FAS_MASK) == FR_FAS_VAL) { + frT[i] = FSync_FAS; + } else if (fr[i] & 0x2) { + frT[i] = FSync_NFAS; + } else + frT[i] = FSync_None; + } + } + break; + default: + for (i = 0; i < 4; i++) { + fr[i] = fr[i + 1]; + frT[i] = frT[i + 1]; + } + /* i = 4 */ + nidx = i * 32; + fr[i] = ib_cp[nidx]; + if ((fr[i] & FR_FAS_MASK) == FR_FAS_VAL) { + frT[i] = FSync_FAS; + } else if (fr[i] & 0x2) { + frT[i] = FSync_NFAS; + } else + frT[i] = FSync_None; + break; + } + switch (frT[0]) { + case FSync_FAS: + switch (fsync_state) { + case FSync_None: + case FSync_AIS: + case FSync_LOS: + fsync_state = FSync_FAS; + startcnt = MFR_SYNC_BITS; + mfr_sync = 0; + break; + case FSync_NFAS: + fsync_state = FSync_FAS; + break; + case FSync_FAS: + if ((frT[2] != FSync_NFAS) && (frT[4] != FSync_NFAS)) { + /* 3 wrong NFAS received - sync lost */ + fsync_state = FSync_LOS; + } else { + /* assume we did receive a NFAS, with wrong Bit 2 */ + fsync_state = FSync_NFAS; + } + break; + } + break; + case FSync_NFAS: + switch (fsync_state) { + case FSync_None: + case FSync_AIS: + case FSync_LOS: + /* cannot happen, since sa new sync always starts with FAS */ + fprintf(stderr, "Line %d: Wrong state %d while processing NFAS\n", __LINE__, fsync_state); + exit(1); + break; + case FSync_FAS: + fsync_state = FSync_NFAS; + break; + case FSync_NFAS: + if ((frT[2] != FSync_FAS) && (frT[4] != FSync_FAS)) { + /* 3 wrong FAS received - sync lost */ + fsync_state = FSync_LOS; + } else { + /* assume we did receive a wrong coded FAS */ + fsync_state = FSync_FAS; + } + break; + } + break; + case FSync_None: + switch (fsync_state) { + case FSync_None: + case FSync_AIS: + case FSync_LOS: + /* cannot happen, since a new sync always starts with FAS */ + fprintf(stderr, "Line %d: Wrong state %d\n", __LINE__, fsync_state); + exit(1); + break; + case FSync_FAS: + if ((frT[2] != FSync_NFAS) && (frT[4] != FSync_NFAS)) { + /* 3 wrong NFAS received - sync lost */ + fsync_state = FSync_LOS; + } else { + /* assume we did receive a NFAS, with wrong Bit 2 */ + fsync_state = FSync_NFAS; + } + break; + case FSync_NFAS: + if ((frT[2] != FSync_FAS) && (frT[4] != FSync_FAS)) { + /* 3 wrong FAS received - sync lost */ + fsync_state = FSync_LOS; + } else { + /* assume we did receive a wrong coded FAS */ + fsync_state = FSync_FAS; + } + break; + } + break; + default: /* not possible here */ + fprintf(stderr, "Line %d: Wrong state %d\n", __LINE__, frT[0]); + exit(1); + break; + } + /* check for multi frame sync now */ + switch (fsync_state) { + case FSync_LOS: + /* start new sync hunting */ + continue; + case FSync_NFAS: + mfr_sync <<= 1; + mfr_sync |= (fr[0] & MFR_SYNC_BIT); + if (startcnt == 0) { + dist = ib_cp - last_mfrs; + if ((mfr_sync & MFR_SYNC_MASK) == MFR_SYNC_VALUE) { + /* sync found */ + if (mfr_state == MFR_State_NotSync) { + mfr_state = MFR_State_Sync; + good_mfr = 1; + analyse_mfr(ib_cp); + } else if (dist == 16 * 32) { + good_mfr++; + analyse_mfr(ib_cp); + } + } else { + if (mfr_state == MFR_State_Sync) { + if (dist == 16 * 32) { + bad_mfr++; + } else if (dist == 32 * 32) { + mfr_state = MFR_State_NotSync; + } + } + } + } else + startcnt--; + break; + case FSync_FAS: + break; + default: + fprintf(stderr, "Wrong state %d\n", fsync_state); + exit(1); + break; + } + ib_cp += 32; + } + if (debuglevel == 2) + printf("\n"); + return 0; +} + +static int fill_buffer(unsigned char *p, int len) +{ + + ib_pos = ib_p - inbuf; + if ((ib_pos + len) >= ib_size) + len = ib_size - ib_pos; + memcpy(ib_p, p, len); + ib_p += len; + return len; +} + +/* returns next start frame */ +static uint8_t *fill_timeslot(uint8_t *p0, int ts, uint8_t *data, int datalen, int repeat) +{ + uint8_t *p = p0; + int i, cnt = repeat; + + while (cnt) { + for (i = 0; i < datalen; i++) { + p[ts] = data[i]; + p += FRAME_SIZE; + } + cnt--; + } + return p; +} + +uint8_t *fill_timeslot_ts0_smf(uint8_t *p0, int ts, int smf, uint8_t fas_err, uint8_t nfas_err, uint8_t mfsw, + uint8_t S, uint8_t A, uint8_t C, uint8_t E, int repeat) +{ + uint8_t *p = p0; + uint8_t i, d[8], a, c, e, n, f, m; + + while (repeat) { + e = E; + if (smf & 1) { + a = A & 0xf; + c = C & 0xf; + n = nfas_err & 0xf; + f = fas_err & 0xf; + m = mfsw & 0xf; + } else { + a = A >> 4; + c = C >> 4; + n = nfas_err >> 4; + f = fas_err >> 4; + m = mfsw >> 4; + } + for (i = 0; i < 8; i++) { + if (i & 1) { /* NFAS */ + if (n & 8) /* nfas error */ + d[i] = 0; + else + d[i] = 2; + n <<= 1; + if (i > 4 && (smf & 1)) { + if (e & 2) + d[i] |= 1; + e <<= 1; + } else { + if (m & 8) + d[i] |= 1; + m <<= 1; + } + d[i] |= (S & 0xF8); + if (a & 8) + d[i] |= 4; + a <<= 1; + } else { /* FAS */ + if (f & 8) /* FAS error */ + d[i] = 0xc8; + else + d[i] = FR_FAS_VAL; + f <<= 1; + if (c & 8) + d[i] |= 1; + c <<= 1; + } + } + p = fill_timeslot(p, ts, d, 8, 1); + smf++; + repeat--; + } + return p; +} + +static uint8_t *calc_and_set_crc4_ts(uint8_t *start, uint8_t ts, uint8_t *first_last_crc, int smf_count) +{ + uint8_t crc = *first_last_crc & 0xf; + uint8_t wrong_crc = *first_last_crc & 0xf0; + uint8_t *p = start; + + while (smf_count) { + if (wrong_crc) + crc = crc + 2; + crc = calc_and_set_crc4_smf(&p[ts], crc & 0xf); + p += SMFR_SIZE; + smf_count--; + } + *first_last_crc = crc; + return p; +} + +static int transmit(int sock, uint8_t *ob, uint16_t len) +{ + struct msghdr mh; + struct iovec iov[2]; + int ret; + struct mISDNhead hh = {PH_DATA_REQ, 1}; + + mh.msg_name = NULL; + mh.msg_namelen = 0; + mh.msg_iov = iov; + mh.msg_iovlen = 2; + mh.msg_control = NULL; + mh.msg_controllen = 0; + mh.msg_flags = 0; + iov[0].iov_base = &hh; + iov[0].iov_len = MISDN_HEADER_LEN; + iov[1].iov_base = ob; + iov[1].iov_len = len; + ret = sendmsg(sock, &mh, 0); + if (ret != (len + MISDN_HEADER_LEN)) { + fprintf(stderr, "Send error %d (%d + %d) - %s\n", ret, + (int)MISDN_HEADER_LEN, len, strerror(errno)); + ret = 0; + } else + ret = len; + return ret; +} + +#define MAX_RECV_BUFFER_SIZE 4200 +static int start_transmit = 1; +static int last_dlen = 64; + +static int receive_ts0dch(int socket) +{ + int ret, cnt, head; + uint8_t buffer[MAX_RECV_BUFFER_SIZE]; + struct mISDNhead *hh = (struct mISDNhead *)buffer; + + ret = recv(socket, buffer, MAX_RECV_BUFFER_SIZE, 0); + if (ret < 0) { + fprintf(stderr, "read error %s\n", strerror(errno)); + return ret; + } +#if 0 + if (cts.cmsg_type == MISDN_TIME_STAMP) { + mt = localtime((time_t *)&cts.tv.tv_sec); + head = printf("%02d.%02d.%04d %02d:%02d:%02d.%06ld", mt->tm_mday, mt->tm_mon + 1, mt->tm_year + 1900, + mt->tm_hour, mt->tm_min, mt->tm_sec, cts.tv.tv_usec); + } else { + cts.tv.tv_sec = 0; + cts.tv.tv_usec = 0; + } +#endif + head = 0; + switch (hh->prim) { + case PH_DATA_IND: + last_dlen = ret - MISDN_HEADER_LEN; + if (!RawReadMode) { + if (start_transmit && RawReadMode == 0) { + ob_p += transmit(socket, ob_p, last_dlen); + start_transmit = 0; + } + cnt = fill_buffer(&buffer[MISDN_HEADER_LEN], last_dlen); + process_data(cnt); + if ((mfr_state == MFR_State_NotSync && debuglevel == 3) || debuglevel == 4) { + head = printf("Got %3d bytes ", last_dlen); + printhex(buffer, MISDN_HEADER_LEN, cnt, head); + } + } else { + head = printf("Got %3d bytes ", last_dlen); + printhex(buffer, MISDN_HEADER_LEN, last_dlen, head); + } + break; + case PH_DATA_CNF: + if (!RawReadMode) { + ob_pos = ob_p - outbuf; + if ((ob_pos + last_dlen) >= ob_size) { + ret = -1; /* stop */ + last_dlen = ob_size - ob_pos; + } + if (debuglevel == 5) { + head = printf("Send %3d bytes ", last_dlen); + printhex(ob_p, 0, last_dlen, head); + } + ob_p += transmit(socket, ob_p, last_dlen); + } + break; + } + return ret; +} + +/* test description sub routines */ +static const char *printhead[] = { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " +}; + +static void print_testdescription(struct fr_cdesc *arg) +{ + struct fr_cdesc *dsc = arg; + int head = 0; + + while (dsc) { + if (dsc->type == ftNone) { + fprintf(stdout, "unexpected end of description\n"); + break; + } else if (dsc->type == ftCtrl_Start) { + fprintf(stdout, "Start of test sequence\n"); + } else if (dsc->type == ftCtrl_Stop) { + fprintf(stdout, "End of test\n"); + break; + } else if (dsc->type == ftCtrl_Repeat) { + fprintf(stdout, "%sdo %d times {\n", printhead[head], dsc->count); + head++; + } else if (dsc->type == ftCtrl_End) { + head--; + fprintf(stdout, "%s}\n", printhead[head]); + } else { + fprintf(stdout, "%s%4d ", printhead[head], dsc->count); + switch (dsc->type) { + case ftAIS: + fprintf(stdout, "%-8s", "AIS"); + break; + /* Basic Frames */ + case ftFAS: + if (dsc->prop & ftPROP_FAIL) + fprintf(stdout, "%-8s", "/FAS"); + else + fprintf(stdout, "%-8s", "FAS"); + break; + case ftBIT2: + if (dsc->prop & ftPROP_FAIL) + fprintf(stdout, "%-8s", "/BIT 2"); + else + fprintf(stdout, "%-8s", "BIT 2"); + break; + /* Sub multi frames */ + case ftSMFA: + fprintf(stdout, "%-8s", "SMF A"); + break; + case ftSMFB: + fprintf(stdout, "%-8s", "SMF B"); + break; + /* Multi frames */ + case ftMFA: + fprintf(stdout, "%-8s", "MF A"); + break; + case ftMFB: + fprintf(stdout, "%-8s", "MF B"); + break; + /* Frames */ + case ftFRAME_A: + fprintf(stdout, "%-8s", "FRAME A"); + break; + case ftFRAME_B: + fprintf(stdout, "%-8s", "FRAME B"); + break; + case ftFRAME_C: + fprintf(stdout, "%-8s", "FRAME C"); + break; + default: + fprintf(stdout, "%-8s", "UNKNOWN"); + break; + } + if (dsc->prop & ftPROP_CRC4) + fprintf(stdout, " (CRC4 Error)"); + if (dsc->prop & ftPROP_MFAS) + fprintf(stdout, " (MFAS Error)"); + if (dsc->prop & ftPROP_TS31) + fprintf(stdout, " (TS 31)"); + if (dsc->prop & ftPROP_START) + fprintf(stdout, " (Start Test)"); + fprintf(stdout, "\n"); + } + dsc++; + } +} + +static void print_flatdescription(struct fr_flatdesc *dsc) +{ + fprintf(stdout, "Start test\n"); + while (dsc) { + if (dsc->type == ftNone) { + fprintf(stdout, "unexpected end of description\n"); + break; + } else if (dsc->type == ftCtrl_Stop) { + fprintf(stdout, "End of test\n"); + break; + } else if (dsc->type == ftAIS) { + fprintf(stdout, "%7d %2d %-6s", dsc->pos, dsc->mf_pos, "AIS"); + } else if (dsc->type == ftFAS) { + if (dsc->prop & ftPROP_FAIL) + fprintf(stdout, "%7d %2d %-6s", dsc->pos, dsc->mf_pos, "/FAS"); + else + fprintf(stdout, "%7d %2d %-6s", dsc->pos, dsc->mf_pos, "FAS"); + } else if (dsc->type == ftBIT2) { + if (dsc->prop & ftPROP_FAIL) + fprintf(stdout, "%7d %2d %-6s", dsc->pos, dsc->mf_pos, "/BIT 2"); + else + fprintf(stdout, "%7d %2d %-6s", dsc->pos, dsc->mf_pos, "BIT 2"); + } + switch (dsc->otype) { + case ftAIS: + fprintf(stdout, "[%-7s]", "AIS"); + break; + /* Basic Frames */ + case ftFAS: + if (dsc->prop & ftPROP_FAIL) + fprintf(stdout, "[%-7s]", "/FAS"); + else + fprintf(stdout, "[%-7s]", "FAS"); + break; + case ftBIT2: + if (dsc->prop & ftPROP_FAIL) + fprintf(stdout, "[%-7s]", "/BIT 2"); + else + fprintf(stdout, "[%-7s]", "BIT 2"); + break; + /* Sub multi frames */ + case ftSMFA: + fprintf(stdout, "[%-7s]", "SMF A"); + break; + case ftSMFB: + fprintf(stdout, "[%-7s]", "SMF B"); + break; + /* Multi frames */ + case ftMFA: + fprintf(stdout, "[%-7s]", "MF A"); + break; + case ftMFB: + fprintf(stdout, "[%-7s]", "MF B"); + break; + /* Frames */ + case ftFRAME_A: + fprintf(stdout, "[%-7s]", "FRAME A"); + break; + case ftFRAME_B: + fprintf(stdout, "[%-7s]", "FRAME B"); + break; + case ftFRAME_C: + fprintf(stdout, "[%-7s]", "FRAME C"); + break; + default: + fprintf(stdout, "[%-7s]", "VOID"); + break; + } + if (dsc->prop & ftPROP_CRC4) + fprintf(stdout, " (CRC4 Error)"); + if (dsc->prop & ftPROP_MFAS) + fprintf(stdout, " (MFAS Error)"); + if (dsc->prop & ftPROP_TS31) + fprintf(stdout, " (TS 31)"); + if (dsc->prop & ftPROP_START) + fprintf(stdout, " (Start Test)"); + fprintf(stdout, "\n"); + dsc++; + } +} + +static int calc_flatcount(struct fr_cdesc *arg) +{ + struct fr_cdesc *dsc = arg; + int count[8], repeat[8]; + int cnt, csp = 0; + + count[0] = 0; + while (dsc) { + if (dsc->type == ftNone) { + fprintf(stderr, "unexpected end of description\n"); + csp = 0; + count[0] = -1; + break; + } + if (dsc->type == ftCtrl_Stop) + break; + if (dsc->type == ftCtrl_Start) { + /* nothing to do */ + } else if (dsc->type == ftCtrl_Repeat) { + csp++; + if (csp >= 8) { + fprintf(stderr, "To deep nesting of loops\n"); + csp = 0; + count[0] = -1; + break; + } + repeat[csp] = dsc->count; + count[csp] = 0; + } else if (dsc->type == ftCtrl_End) { + if (csp < 1) { + fprintf(stderr, "End of description, but no Repeatblock\n"); + csp = 0; + count[0] = -1; + break; + } + cnt = repeat[csp] * count[csp]; + csp--; + count[csp] += cnt; + } else { + count[csp] += (dsc->subcnt * dsc->count); + } + dsc++; + } + if (csp != 0) { + fprintf(stderr, "End of description, but repeat level %d (not 0)\n", csp); + csp = 0; + count[0] = -1; + } + return count[0]; +} + +static struct fr_flatdesc *make_flat_description(struct fr_cdesc *test, struct fr_flatdesc *begin) +{ + struct fr_cdesc *dsc = test; + struct fr_flatdesc *flat = begin; + int count[8], repeat[8]; + struct fr_flatdesc *seq, *end, *start[8]; + int cnt, i, csp = 0, pos, mfpos; + + pos = flat->pos; + mfpos = flat->mf_pos; + while (dsc) { + if (dsc->type == ftNone) { + fprintf(stderr, "unexpected end of description\n"); + flat = NULL; + break; + } + if (dsc->type == ftCtrl_Stop) { + flat->pos = pos; + flat->type = dsc->type; + break; + } + if (dsc->type == ftCtrl_Start) { + /* nothing to do */ + flat->prop = ftPROP_START; + } else if (dsc->type == ftCtrl_Repeat) { + csp++; + if (csp >= 8) { + fprintf(stderr, "To deep nesting of loops\n"); + csp = 0; + flat = NULL; + break; + } + repeat[csp] = dsc->count; + start[csp] = flat; + count[csp] = 0; + } else if (dsc->type == ftCtrl_End) { + if (csp < 1) { + fprintf(stderr, "End of description, but no Repeatblock\n"); + flat = NULL; + break; + } + end = flat; + repeat[csp]--; /* one already done */ + while (repeat[csp]) { + seq = start[csp]; + while (seq != end) { + *flat = *seq; + flat->pos = pos; + flat->prop &= ~ftPROP_START; + seq++; + flat++; + pos++; + } + --repeat[csp]; + } + csp--; + } else { + for (cnt = 0; cnt < dsc->count; cnt++) { + switch (dsc->type) { + case ftAIS: + /* Basic Frames */ + case ftFAS: + case ftBIT2: + flat->pos = pos; + flat->type = dsc->type; + flat->otype = dsc->type; + flat->prop |= dsc->prop; + flat++; + pos++; + break; + /* Sub multi frames */ + case ftSMFA: + for (i = 0; i < 8; i++) { + flat->pos = pos; + flat->otype = dsc->type; + if (i & 1) { + flat->type = ftBIT2; + } else { + flat->type = ftFAS; + } + flat++; + pos++; + } + break; + case ftSMFB: + for (i = 0; i < 8; i++) { + flat->pos = pos; + flat->otype = dsc->type; + if (i & 1) { + flat->type = ftBIT2; + } else { + flat->type = ftFAS; + } + flat->prop |= dsc->prop; + flat++; + pos++; + } + break; + /* Multi frames */ + case ftMFA: + for (i = 0; i < 16; i++) { + flat->pos = pos; + flat->otype = dsc->type; + if (i & 1) { + flat->type = ftBIT2; + } else { + flat->type = ftFAS; + } + flat++; + pos++; + } + break; + case ftMFB: + for (i = 0; i < 16; i++) { + flat->pos = pos; + flat->otype = dsc->type; + if (i & 1) { + flat->type = ftBIT2; + } else { + flat->type = ftFAS; + } + flat->prop |= ftPROP_MFAS; + flat++; + pos++; + } + break; + /* Frames */ + case ftFRAME_A: + flat->pos = pos; + flat->otype = dsc->type; + flat->type = ftFAS; + flat++; + pos++; + flat->pos = pos; + flat->otype = dsc->type; + flat->type = ftBIT2; + flat++; + pos++; + break; + case ftFRAME_B: + flat->pos = pos; + flat->otype = dsc->type; + flat->type = ftFAS; + flat->prop |= ftPROP_TS31; + flat++; + pos++; + flat->pos = pos; + flat->otype = dsc->type; + flat->type = ftBIT2; + flat->prop |= ftPROP_TS31; + flat++; + pos++; + break; + case ftFRAME_C: + flat->pos = pos; + flat->otype = dsc->type; + flat->type = ftFAS; + flat->prop |= ftPROP_FAIL | ftPROP_TS31; + flat++; + pos++; + flat->pos = pos; + flat->otype = dsc->type; + flat->type = ftBIT2; + flat->prop |= ftPROP_TS31; + flat++; + pos++; + break; + default: + /* never */ + fprintf(stderr, "Got wrong type %x\n", dsc->type); + exit(1); + } + } + } + dsc++; + } + if (!flat) + return flat; + flat = begin; + mfpos = flat->mf_pos; + while (flat) { + if (flat->type == ftNone) { + fprintf(stdout, "unexpected end of description\n"); + flat = NULL; + break; + } else if (flat->type == ftCtrl_Stop) { + flat->mf_pos = mfpos; + break; + } else if (flat->type == ftAIS) { + flat->mf_pos = 0xff; + flat->mf_pos = 14; + } else if (flat->type == ftFAS) { + if (mfpos & 1) /* reset */ + mfpos = 0; + } else if (flat->type == ftBIT2) { + if (!(mfpos & 1)) + mfpos = 1; + } + flat->mf_pos = mfpos; + mfpos++; + if (mfpos > 15) + mfpos = 0; + flat++; + } + return flat; +} + +static struct fr_data *gen_flat_frame_desc(struct fr_cdesc *dsc) +{ + struct fr_data loc_frd, *frd; + struct fr_flatdesc *flat_dsc; + int cnt, sum, pre; + + pre = calc_flatcount(preamble); + cnt = calc_flatcount(dsc); + sum = pre + cnt; + loc_frd.count = sum; + flat_dsc = calloc(sum + 2, sizeof(*flat_dsc)); /* reserve for stop */ + if (!flat_dsc) { + fprintf(stderr, "No memory to allocate %d * %zd bytes for flat description\n", loc_frd.count, sizeof(*flat_dsc)); + return NULL; + } + loc_frd.desc = flat_dsc; + flat_dsc = make_flat_description(preamble, flat_dsc); + if (!flat_dsc) { + fprintf(stderr, "Error while generating flat description of preamble\n"); + free(flat_dsc); + return NULL; + } + flat_dsc = make_flat_description(dsc, flat_dsc); + if (!flat_dsc) { + fprintf(stderr, "Error while generating flat description\n"); + free(flat_dsc); + return NULL; + } + frd = malloc(sizeof(*frd)); + if (!frd) { + fprintf(stderr, "No memory to allocate %zd bytes\n", sizeof(*frd)); + free(flat_dsc); + return NULL; + } + *frd = loc_frd; + return frd; +} + +static int gen_flat_frame_data(struct fr_data *frd) { + struct fr_flatdesc *flat; + size_t size; + int cnt, ret = 0; + uint8_t crc, *p, dch_flags = 0x7e; + + flat = frd->desc; + size = frd->count; + size *= FRAME_SIZE; + frd->data_size = size; + frd->data = malloc(size + 100 * FRAME_SIZE); /* Reserve to avoid crash when manipulate frames on the end */ + if (!frd->data) { + fprintf(stderr, "No memory to allocate %zd + %d bytes\n", size, 100 * FRAME_SIZE); + flat = NULL; + ret = -ENOMEM; + } + memset(frd->data, 0xff, size + 100 * FRAME_SIZE); + p = frd->data; + fill_timeslot(p, 16, &dch_flags, 1, frd->count); + while (flat) { + flat->data = p; + if (flat->type == ftNone) { + fprintf(stdout, "unexpected end of description\n"); + free(frd->data); + frd->data = NULL; + ret = -EINVAL; + break; + } else if (flat->type == ftCtrl_Stop) { + fprintf(stdout, "End of test\n"); + break; + } else if (flat->type == ftAIS) { + memset(p, 0xff, FRAME_SIZE); + } else if (flat->type == ftFAS) { + if (flat->prop & ftPROP_FAIL) + *p = FR_FAS_VAL_FAIL; + else + *p = FR_FAS_VAL; + if (flat->prop & ftPROP_TS31) + p[31] = FR_NFAS_B2; + } else if (flat->type == ftBIT2) { + if (flat->prop & ftPROP_FAIL) + *p = FR_NFAS_B2_FAIL; + else + *p = FR_NFAS_B2; + if ((flat->mf_pos & 0xf) == 5) { + if (!(flat->prop & ftPROP_MFAS)) + *p |= 1; + } else if ((flat->mf_pos & 0xf) > 7) { + *p |= 1; + } + if (flat->prop & ftPROP_TS31) + p[31] = FR_FAS_VAL; + } + p += FRAME_SIZE; + flat++; + } + p = frd->data; + cnt = frd->count/8; + crc = 0; /* start value */ + flat = frd->desc; + while (flat) { + if (flat->type == ftNone) { + fprintf(stdout, "unexpected end of description\n"); + free(frd->data); + frd->data = NULL; + ret = -EINVAL; + break; + } else if (flat->type == ftCtrl_Stop) { + fprintf(stdout, "End of test\n"); + break; + } else if (flat->type == ftAIS) { + crc = 0; + } else { + if ((flat->mf_pos & 0x7) == 0) { + calc_and_set_crc4_ts(flat->data, 0, &crc, 1); + } + if ((flat->mf_pos & 0x7) == 2) { + if (flat->prop & ftPROP_CRC4) { + /* insert a bit failure in TS 3 (0xFF -> 0xEF) */ + flat->data[3] = 0xef; + } + } + } + flat++; + } + return ret; +} + +int +main(argc, argv) +int argc; +char *argv[]; +{ + int i, channel; + int log_socket; + struct sockaddr_mISDN log_addr; + int buflen = 4104; + u_char buffer[buflen]; + int result; + int cnt, dlen; + struct mISDN_devinfo di; + struct mISDNhead *hh; + struct mISDNversion ver; + struct pollfd pfd[8]; + int pfd_nr; + struct mISDN_ctrl_req creq; + + result = opt_parse(argc, argv); + if (result) { + exit(1); + } + calc_bitswap_table(); + + cnt = calc_flatcount(preamble); + fprintf(stdout, "preamble: %d test: %d\n", cnt, calc_flatcount(Test)); + + if (ListMode == 1) { + print_testdescription(Test); + return 0; + } + TestData = gen_flat_frame_desc(Test); + if (!TestData) { + fprintf(stdout, "Did not generate flat description\n"); + exit(1); + } + if (ListMode == 2) { + print_flatdescription(TestData->desc); + return 0; + } + result = gen_flat_frame_data(TestData); + if (result) { + fprintf(stderr,"Error generating test data\n"); + exit(1); + } + + if (cardnr < 0) { + fprintf(stderr,"card nr may not be negative\n"); + exit(1); + } + + if ((log_socket = socket(PF_ISDN, SOCK_RAW, 0)) < 0) { + printf("could not open socket %s\n", strerror(errno)); + exit(1); + } + + result = ioctl(log_socket, IMGETVERSION, &ver); + if (result < 0) { + printf("ioctl error %s\n", strerror(errno)); + exit(1); + } + printf("mISDN kernel version %d.%02d.%d found\n", ver.major, ver.minor, ver.release); + printf("mISDN user version %d.%02d.%d found\n", MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE); + + if (ver.major != MISDN_MAJOR_VERSION) { + printf("VERSION incompatible please update\n"); + exit(1); + } + + result = ioctl(log_socket, IMGETCOUNT, &cnt); + if (result < 0) { + printf("ioctl error %s\n", strerror(errno)); + exit(1); + } else + printf("%d controller%s found\n", cnt, (cnt==1)?"":"s"); + + di.id = cardnr; + result = ioctl(log_socket, IMGETDEVINFO, &di); + if (result < 0) { + printf("ioctl error %s\n", strerror(errno)); + } else { + printf(" id: %d\n", di.id); + printf(" Dprotocols: %08x\n", di.Dprotocols); + printf(" Bprotocols: %08x\n", di.Bprotocols); + printf(" protocol: %d\n", di.protocol); + printf(" channelmap: "); + for (i = MISDN_CHMAP_SIZE - 1; i >= 0; i--) + printf("%02x", di.channelmap[i]); + printf("\n"); + printf(" nrbchan: %d\n", di.nrbchan); + printf(" name: %s\n", di.name); + } + + close(log_socket); + outbuf = TestData->data; + ob_size = TestData->data_size; + ob_end = outbuf + ob_size; + ib_size = ob_size; + ib_size += (5 * MFR_SIZE); + inbuf = malloc(ib_size + (5 * MFR_SIZE)); + if (!inbuf) { + fprintf(stderr, "Could not allocate in buffer (%d bytes)\n", ib_size + (5 * MFR_SIZE)); + exit(1); + } else if (debuglevel) + printf("Allocated in buffer %d bytes (Reserve:%d)\n", ib_size, 10 * MFR_SIZE); + + ib_p = inbuf; + ib_cp = inbuf; + ib_end = outbuf + ib_size; + + /* Ready for transmit */ + ob_p = outbuf; + + if ((log_socket = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW)) < 0) { + printf("could not open log socket %s\n", strerror(errno)); + exit(1); + } + + log_addr.family = AF_ISDN; + log_addr.dev = cardnr; + + result = -1; + channel = 0; + + log_addr.channel = (unsigned char)channel; + result = bind(log_socket, (struct sockaddr *) &log_addr, sizeof(log_addr)); + printf("log bind ch(%i) return %d\n", log_addr.channel, result); + if (result < 0) { + printf("log bind error %s\n", strerror(errno)); + close(log_socket); + exit(1); + } + + result = fcntl(log_socket, F_SETFL, O_NONBLOCK); + if (result < 0) { + printf("log F_SETFL O_NONBLOCK error %s\n", strerror(errno)); + close(log_socket); + exit(1); + } + pfd[0].fd = log_socket; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + pfd_nr = 1; + + hh = (struct mISDNhead *)buffer; + + /* This set the register values in the card so, that the TS0 is not in full transparent mode, + * so the receiver can syncronize - this allows to get the TS0 data on byte boundaries, so bit schifting all + * incoming data is not needed. After we did detect syncron state for 3 times, will will switch off + * autosync and put TS0 into full transparent mode */ + + creq.op = MISDN_CTRL_L1_TS0_MODE; + creq.channel = 0; + creq.p1 = 0x06; /* R_RX_SL0_CFG0 = (V_AUTOSYNC | V_AUTO_RECO) */ + creq.p2 = 0x31; /* R_TX_SL0_CFG1 = (V_TX_MF | V_TX_E | V_INV_E) */ + creq.p3 = 0; + if (debuglevel) + fprintf(stdout,"L1 TS0 ioctl R_RX_SL0_CFG0=%02x R_TX_SL0_CFG1=%02x\n", creq.p1, creq.p2); + result = ioctl(log_socket, IMCTRLREQ, &creq); + if (debuglevel) + fprintf(stdout,"L1 TS0 ioctl old register values R_RX_SL0_CFG0=%02x R_TX_SL0_CFG1=%02x\n", creq.p1, creq.p2); + if (result < 0) { + fprintf(stdout, "Error on MISDN_CTRL_L1_TS0_MODE ioctl - %s\n", strerror(errno)); + close(log_socket); + exit(1); + } + + hh->prim = PH_ACTIVATE_REQ; + hh->id = MISDN_ID_ANY; + result = sendto(log_socket, buffer, MISDN_HEADER_LEN, 0, NULL, 0); + + if (result < 0) { + fprintf(stdout, "could not send ACTIVATE_REQ %s\n", strerror(errno)); + close(log_socket); + exit(1); + } + + /* Disable RX for the sync search time */ + creq.op = MISDN_CTRL_RX_OFF; + creq.channel = 0; + creq.p1 = 1; + creq.p2 = 0; + creq.p3 = 0; + result = ioctl(log_socket, IMCTRLREQ, &creq); + if (result < 0) { + fprintf(stdout, "Error on MISDN_CTRL_RX_OFF ioctl - %s\n", strerror(errno)); + close(log_socket); + exit(1); + } + if (debuglevel) + fprintf(stdout,"RX_OFF result %d ioctl p1=%02x p2=%02x p3=%02x\n", + result, creq.p1, creq.p2, creq.p3); + + creq.op = MISDN_CTRL_L1_GET_SYNC_INFO; + creq.channel = 0; + cnt = 0; + /* Wait for sync - this will make sure that we do not need bit shifting incomming data */ + for (i = 0; i < 5000; i++) { + result = ioctl(log_socket, IMCTRLREQ, &creq); + if (result < 0) { + fprintf(stdout, "Error on MISDN_CTRL_L1_GET_SYNC_INFO ioctl - %s\n", strerror(errno)); + close(log_socket); + exit(1); + } + if (debuglevel) + fprintf(stdout,"L1 GET_SYNC_INFO ioctl p1=%02x p2=%02x p3=%02x\n", + creq.p1, creq.p2, creq.p3); + if ((creq.p1 & 0xff07) == 0x2701) { + cnt++; + if (cnt == 3) + break; + i--; + } else + cnt = 0; + usleep(100000); + }; + + if (cnt != 3) { + fprintf(stdout,"L1 ts0 sync state not reached\n"); + close(log_socket); + exit(1); + } else + fprintf(stdout,"L1 ts0 sync state reached (need %d iterations)\n", i); + + /* reenable receive */ + creq.op = MISDN_CTRL_RX_OFF; + creq.channel = 0; + creq.p1 = 0; + creq.p2 = 0; + creq.p3 = 0; + result = ioctl(log_socket, IMCTRLREQ, &creq); + if (result < 0) { + fprintf(stdout, "Error on MISDN_CTRL_RX_OFF ioctl - %s\n", strerror(errno)); + close(log_socket); + exit(1); + } + if (debuglevel) + fprintf(stdout,"RX_OFF ioctl p1=%02x p2=%02x p3=%02x\n", creq.p1, creq.p2, creq.p3); + + creq.op = MISDN_CTRL_L1_TS0_MODE; + creq.channel = 0; + creq.p1 = 0x01; /* R_RX_SL0_CFG0 = (V_NO_INSYNC) */ + creq.p2 = 0x03; /* R_TX_SL0_CFG1 = (V_TX_MF | V_TRP_SL0) */ + creq.p3 = 0; + if (debuglevel) + fprintf(stdout,"L1 TS0 ioctl R_RX_SL0_CFG0=%02x R_TX_SL0_CFG1=%02x\n", creq.p1, creq.p2); + result = ioctl(log_socket, IMCTRLREQ, &creq); + if (debuglevel) + fprintf(stdout,"L1 TS0 ioctl old register values R_RX_SL0_CFG0=%02x R_TX_SL0_CFG1=%02x\n", creq.p1, creq.p2); + if (result < 0) { + fprintf(stdout, "Error on MISDN_CTRL_L1_TS0_MODE ioctl - %s\n", strerror(errno)); + close(log_socket); + exit(1); + } + + dlen = 64; + while (1) { + result = poll(pfd, pfd_nr, 1000); + if (result < 0) { + fprintf(stderr, "Poll error %s\n", strerror(errno)); + continue; + } else if (result == 0) { + fprintf(stderr, "Poll timeout restart\n"); + continue; + } + if (pfd[0].revents) { + dlen = receive_ts0dch(log_socket); + if (dlen < 1) /* end of data */ + break; + } + } + close(log_socket); + return 0; +} diff --git a/tools/Makefile.am b/tools/Makefile.am index 661d796..bb63c2b 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,11 +1,12 @@ -bin_PROGRAMS = misdn_info misdn_log +bin_PROGRAMS = misdn_info misdn_log misdn_E1test sbin_PROGRAMS = misdn_rename misdn_cleanl2 misdn_info_SOURCES = info.c misdn_log_SOURCES = loghex.c misdn_rename_SOURCES = rename.c misdn_cleanl2_SOURCES = cleanl2.c +misdn_E1test_SOURCES = E1test.c -AM_CPPFLAGS = -I$(top_srcdir)/include +AM_CPPFLAGS = -Wall -I$(top_srcdir)/include CLEANFILES = *~ diff --git a/tools/Makefile.in b/tools/Makefile.in index dafe65d..399ea90 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -34,7 +34,8 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -bin_PROGRAMS = misdn_info$(EXEEXT) misdn_log$(EXEEXT) +bin_PROGRAMS = misdn_info$(EXEEXT) misdn_log$(EXEEXT) \ + misdn_E1test$(EXEEXT) sbin_PROGRAMS = misdn_rename$(EXEEXT) misdn_cleanl2$(EXEEXT) subdir = tools DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in @@ -49,6 +50,9 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) +am_misdn_E1test_OBJECTS = E1test.$(OBJEXT) +misdn_E1test_OBJECTS = $(am_misdn_E1test_OBJECTS) +misdn_E1test_LDADD = $(LDADD) am_misdn_cleanl2_OBJECTS = cleanl2.$(OBJEXT) misdn_cleanl2_OBJECTS = $(am_misdn_cleanl2_OBJECTS) misdn_cleanl2_LDADD = $(LDADD) @@ -74,10 +78,12 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(misdn_cleanl2_SOURCES) $(misdn_info_SOURCES) \ - $(misdn_log_SOURCES) $(misdn_rename_SOURCES) -DIST_SOURCES = $(misdn_cleanl2_SOURCES) $(misdn_info_SOURCES) \ - $(misdn_log_SOURCES) $(misdn_rename_SOURCES) +SOURCES = $(misdn_E1test_SOURCES) $(misdn_cleanl2_SOURCES) \ + $(misdn_info_SOURCES) $(misdn_log_SOURCES) \ + $(misdn_rename_SOURCES) +DIST_SOURCES = $(misdn_E1test_SOURCES) $(misdn_cleanl2_SOURCES) \ + $(misdn_info_SOURCES) $(misdn_log_SOURCES) \ + $(misdn_rename_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -205,7 +211,8 @@ misdn_info_SOURCES = info.c misdn_log_SOURCES = loghex.c misdn_rename_SOURCES = rename.c misdn_cleanl2_SOURCES = cleanl2.c -AM_CPPFLAGS = -I$(top_srcdir)/include +misdn_E1test_SOURCES = E1test.c +AM_CPPFLAGS = -Wall -I$(top_srcdir)/include CLEANFILES = *~ all: all-am @@ -327,6 +334,9 @@ clean-sbinPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list +misdn_E1test$(EXEEXT): $(misdn_E1test_OBJECTS) $(misdn_E1test_DEPENDENCIES) + @rm -f misdn_E1test$(EXEEXT) + $(LINK) $(misdn_E1test_OBJECTS) $(misdn_E1test_LDADD) $(LIBS) misdn_cleanl2$(EXEEXT): $(misdn_cleanl2_OBJECTS) $(misdn_cleanl2_DEPENDENCIES) @rm -f misdn_cleanl2$(EXEEXT) $(LINK) $(misdn_cleanl2_OBJECTS) $(misdn_cleanl2_LDADD) $(LIBS) @@ -346,6 +356,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/E1test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cleanl2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loghex.Po@am__quote@