diff options
author | root <root@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-08-17 22:04:22 +0000 |
---|---|---|
committer | root <root@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-08-17 22:04:22 +0000 |
commit | b1742b89db7d0f0335f59a3b701895683e0f3d2f (patch) | |
tree | 4a433ea2f38280b587e2d14eb297ea95d2d710dd /channels/misdn | |
parent | 62245abb42c1e23df30e8bb1b80920750fcfc7b6 (diff) |
automerge commit
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.2-netsec@40332 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/misdn')
-rw-r--r-- | channels/misdn/Makefile | 58 | ||||
-rw-r--r-- | channels/misdn/chan_misdn_config.h | 29 | ||||
-rw-r--r-- | channels/misdn/fac.c | 313 | ||||
-rw-r--r-- | channels/misdn/fac.h | 8 | ||||
-rw-r--r-- | channels/misdn/ie.c | 353 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.c | 2791 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.h | 175 | ||||
-rw-r--r-- | channels/misdn/isdn_lib_intern.h | 24 | ||||
-rw-r--r-- | channels/misdn/isdn_msg_parser.c | 384 | ||||
-rw-r--r-- | channels/misdn/mISDN.patch | 2500 | ||||
-rw-r--r-- | channels/misdn/portinfo.c | 197 |
11 files changed, 2603 insertions, 4229 deletions
diff --git a/channels/misdn/Makefile b/channels/misdn/Makefile index e0e18cf85..1374e75e3 100644 --- a/channels/misdn/Makefile +++ b/channels/misdn/Makefile @@ -5,10 +5,13 @@ # # Verify those options with main Makefile -CFLAGS += -pipe -c -DMISDNUSER_JOLLY +CFLAGS = -pipe -c -Wall -ggdb +ifeq ($(shell uname -m),x86_64) +CFLAGS += -fPIC +endif SOURCES = isdn_lib.c isdn_msg_parser.c OBJDIR = . -OBJS = isdn_lib.o isdn_msg_parser.o +OBJS = isdn_lib.o isdn_msg_parser.o fac.o all: chan_misdn_lib.a @@ -16,57 +19,24 @@ all: chan_misdn_lib.a %.o: %.c $(CC) $(CFLAGS) -o $@ $< - + chan_misdn_lib.a: $(OBJS) ar crv $@ $(OBJS) -misdn: test_preempt - if [ ! -d lib ] ; then \ - mkdir lib; \ - cd lib ; \ - wget http://isdn.jolly.de/download/v3.1/mISDN_for_PBX4Linux-3.0.tar.gz ;\ - tar xzf mISDN_for_PBX4Linux-3.0.tar.gz; \ - wget http://isdn.jolly.de/download/v3.1/mISDNuser_for_PBX4Linux-3.0.tar.gz ;\ - tar xzf mISDNuser_for_PBX4Linux-3.0.tar.gz ;\ - cd mISDN; patch -p1 <../../mISDN.patch; \ - cd ../mISDNuser ; patch -p1 <../../mISDNuser.patch; \ - fi +misdn: + @mkdir -p lib + cd lib ; cvs -d:pserver:anonymous:readonly@cvs.isdn4linux.de:/i4ldev co mISDN mISDNuser ; cd lib/mISDN ; make install cd lib/mISDNuser ; make install -LINUX=/lib/modules/$(uname -r)/build -GCCVERSION=$(shell $(CC) --version | grep GCC | cut -d " " -f 3 | cut -d "." -f 1) - -test_preempt: - @if grep 'CONFIG_DEBUG_SPINLOCK=y' $(LINUX)/.config ; then \ - echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nDisable the DEBUG_SPINLOCK Setting in your Kernel Config.\n with this option set, mISDN will not work! \n\n" ;\ - read ; \ - exit 1 ; \ - fi - @if grep 'CONFIG_DEBUG_SPINLOCK_SLEEP=y' $(LINUX)/.config ; then \ - echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nDisable the DEBUG_SPINLOCK_SLEEP Setting in your Kernel Config.\n with this option set, mISDN will not work! \n\n" ;\ - read ; \ - exit 1 ; \ - fi - @if grep 'CONFIG_SMP=y' $(LINUX)/.config ; then \ - echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nDisable the SMP Setting in your Kernel Config.\n\n" ; \ - read ; \ - exit 1 ; \ - fi - @if test "$(GCCVERSION)" -gt 3 ; then \ - echo -e "\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!\nYou're using GCC 4! Please downgrade to gcc-3.x and type:\nexport CC=gcc-3.x\nbefore issuing make again.\nyou won't have success with gcc-4!\n\n" ; \ - read ; \ - exit 1 ; \ - fi - - - +portinfo: portinfo.o + $(CC) -L/usr/lib -o $@ $^ -lisdnnet -lmISDN -lpthread + + FORCE: clean: rm -rf *.a *.o *.so - -misdn_clean: rm -rf lib - + rm -rf portinfo diff --git a/channels/misdn/chan_misdn_config.h b/channels/misdn/chan_misdn_config.h index 250a74e54..58fca2c8b 100644 --- a/channels/misdn/chan_misdn_config.h +++ b/channels/misdn/chan_misdn_config.h @@ -22,47 +22,58 @@ enum misdn_cfg_elements { /* port config items */ MISDN_CFG_FIRST = 0, - MISDN_CFG_PTP, /* int (bool) */ MISDN_CFG_GROUPNAME, /* char[] */ + MISDN_CFG_ALLOWED_BEARERS, /* char[] */ + MISDN_CFG_FAR_ALERTING, /* int (bool) */ MISDN_CFG_RXGAIN, /* int */ MISDN_CFG_TXGAIN, /* int */ MISDN_CFG_TE_CHOOSE_CHANNEL, /* int (bool) */ + MISDN_CFG_PMP_L1_CHECK, /* int (bool) */ + MISDN_CFG_ALARM_BLOCK, /* int (bool) */ + MISDN_CFG_HDLC, /* int (bool) */ MISDN_CFG_CONTEXT, /* char[] */ MISDN_CFG_LANGUAGE, /* char[] */ + MISDN_CFG_MUSICCLASS, /* char[] */ MISDN_CFG_CALLERID, /* char[] */ MISDN_CFG_METHOD, /* char[] */ MISDN_CFG_DIALPLAN, /* int */ MISDN_CFG_LOCALDIALPLAN, /* int */ + MISDN_CFG_CPNDIALPLAN, /* int */ MISDN_CFG_NATPREFIX, /* char[] */ MISDN_CFG_INTERNATPREFIX, /* char[] */ - MISDN_CFG_PRES, /* int (bool) */ + MISDN_CFG_PRES, /* int */ + MISDN_CFG_SCREEN, /* int */ MISDN_CFG_ALWAYS_IMMEDIATE, /* int (bool) */ + MISDN_CFG_NODIALTONE, /* int (bool) */ MISDN_CFG_IMMEDIATE, /* int (bool) */ + MISDN_CFG_SENDDTMF, /* int (bool) */ MISDN_CFG_HOLD_ALLOWED, /* int (bool) */ MISDN_CFG_EARLY_BCONNECT, /* int (bool) */ - MISDN_CFG_USE_CALLINGPRES, /* int (bool) */ + MISDN_CFG_INCOMING_EARLY_AUDIO, /* int (bool) */ MISDN_CFG_ECHOCANCEL, /* int */ MISDN_CFG_ECHOCANCELWHENBRIDGED, /* int (bool) */ - MISDN_CFG_ECHOTRAINING, /* int (bool) */ + MISDN_CFG_NEED_MORE_INFOS, /* bool */ + MISDN_CFG_JITTERBUFFER, /* int */ + MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, /* int */ MISDN_CFG_CALLGROUP, /* ast_group_t */ MISDN_CFG_PICKUPGROUP, /* ast_group_t */ MISDN_CFG_MSNS, /* char[] */ + MISDN_CFG_PTP, /* int (bool) */ MISDN_CFG_LAST, /* general config items */ MISDN_GEN_FIRST, + MISDN_GEN_MISDN_INIT, /* char[] */ MISDN_GEN_DEBUG, /* int */ MISDN_GEN_TRACEFILE, /* char[] */ - MISDN_GEN_TRACE_CALLS, /* int (bool) */ - MISDN_GEN_TRACE_DIR, /* char[] */ MISDN_GEN_BRIDGING, /* int (bool) */ MISDN_GEN_STOP_TONE, /* int (bool) */ MISDN_GEN_APPEND_DIGITS2EXTEN, /* int (bool) */ - MISDN_GEN_L1_INFO_OK, /* int (bool) */ - MISDN_GEN_CLEAR_L3, /* int (bool) */ MISDN_GEN_DYNAMIC_CRYPT, /* int (bool) */ MISDN_GEN_CRYPT_PREFIX, /* char[] */ MISDN_GEN_CRYPT_KEYS, /* char[] */ + MISDN_GEN_NTDEBUGFLAGS, /* int */ + MISDN_GEN_NTDEBUGFILE, /* char[] */ MISDN_GEN_LAST }; @@ -76,6 +87,8 @@ void misdn_cfg_init(int max_ports); void misdn_cfg_reload(void); void misdn_cfg_destroy(void); +void misdn_cfg_update_ptp( void ); + /* if you requst a general config element, the port value is ignored. if the requested * value is not available, or the buffer is too small, the buffer will be nulled (in * case of a char* only its first byte will be nulled). */ diff --git a/channels/misdn/fac.c b/channels/misdn/fac.c new file mode 100644 index 000000000..383a60f26 --- /dev/null +++ b/channels/misdn/fac.c @@ -0,0 +1,313 @@ + +#include "isdn_lib_intern.h" +#include "isdn_lib.h" + +#include "string.h" + + + + +#define CENTREX_ID 0xa1 +#define CALLDEFLECT_ID 0xa1 + +/** + This file covers the encoding and decoding of facility messages and + facility information elements. + + There will be 2 Functions as Interface: + + fac_enc( char **ntmsg, msg_t * msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc) + fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc); + + Those will either read the union facility or fill it. + + internally, we will have deconding and encoding functions for each facility + IE. + +**/ + + +/* support stuff */ +static void strnncpy(unsigned char *dest, unsigned char *src, int len, int dst_len) +{ + if (len > dst_len-1) + len = dst_len-1; + strncpy((char *)dest, (char *)src, len); + dest[len] = '\0'; +} + + + + +/**********************/ +/*** FACILITY STUFF ***/ +/**********************/ + + +/* IE_FACILITY */ +void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc) +{ + unsigned char *p; + Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN); + int l; + + + if (!facility || facility_len<=0) + { + return; + } + + + l = facility_len; + p = msg_put(msg, l+2); + if (nt) + *ntmode = p+1; + else + qi->QI_ELEMENT(facility) = p - (unsigned char *)qi - sizeof(Q931_info_t); + p[0] = IE_FACILITY; + p[1] = l; + memcpy(p+2, facility, facility_len); +} + + +/* facility for siemens CENTEX (known parts implemented only) */ +void enc_ie_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc) +{ + unsigned char centrex[256]; + int i = 0; + + if (!cnip) + return; + + /* centrex facility */ + centrex[i++] = FACILITY_CENTREX; + centrex[i++] = CENTREX_ID; + + /* cnip */ + if (strlen((char *)cnip) > 15) + { +/* if (options.deb & DEBUG_PORT) */ + cb_log(1,0,"%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__); + cnip[15] = '\0'; + } + /* dunno what the 8 bytes mean */ + if (setup) + { + centrex[i++] = 0x17; + centrex[i++] = 0x02; + centrex[i++] = 0x02; + centrex[i++] = 0x44; + centrex[i++] = 0x18; + centrex[i++] = 0x02; + centrex[i++] = 0x01; + centrex[i++] = 0x09; + } else + { + centrex[i++] = 0x18; + centrex[i++] = 0x02; + centrex[i++] = 0x02; + centrex[i++] = 0x81; + centrex[i++] = 0x09; + centrex[i++] = 0x02; + centrex[i++] = 0x01; + centrex[i++] = 0x0a; + } + + centrex[i++] = 0x80; + centrex[i++] = strlen((char *)cnip); + strcpy((char *)(¢rex[i]), (char *)cnip); + i += strlen((char *)cnip); + cb_log(4,0," cnip='%s'\n", cnip); + + /* encode facility */ + enc_ie_facility(ntmode, msg, centrex, i, nt , bc); +} + +void dec_ie_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *centrex, int facility_len, unsigned char *cnip, int cnip_len, int nt, struct misdn_bchannel *bc) +{ + + int i = 0; + *cnip = '\0'; + + if (facility_len >= 2) + { + if (centrex[i++] != FACILITY_CENTREX) + return; + if (centrex[i++] != CENTREX_ID) + return; + } + + /* loop sub IEs of facility */ + while(facility_len > i+1) + { + if (centrex[i+1]+i+1 > facility_len) + { + printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__); + return; + } + switch(centrex[i]) + { + case 0x80: + strnncpy(cnip, ¢rex[i+2], centrex[i+1], cnip_len); + cb_log(4,0," CENTREX cnip='%s'\n", cnip); + break; + } + i += 1+centrex[i+1]; + } +} + + + + +/* facility for CALL Deflect (known parts implemented only) */ +void enc_ie_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc) +{ + unsigned char fac[256]; + + if (!nr) + return; + + int len = strlen(nr); + /* calldeflect facility */ + + /* cnip */ + if (strlen((char *)nr) > 15) + { +/* if (options.deb & DEBUG_PORT) */ + cb_log(1,0,"%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__); + nr[15] = '\0'; + } + + fac[0]=FACILITY_CALLDEFLECT; // .. + fac[1]=CALLDEFLECT_ID; + fac[2]=0x0f + len; // strlen destination + 15 = 26 + fac[3]=0x02; + fac[4]=0x01; + //fac[5]=0x70; + fac[5]=0x09; + fac[6]=0x02; + fac[7]=0x01; + fac[8]=0x0d; + fac[9]=0x30; + fac[10]=0x07 + len; // strlen destination + 7 = 18 + fac[11]=0x30; // ...hm 0x30 + fac[12]=0x02+ len; // strlen destination + 2 + fac[13]=0x80; // CLIP + fac[14]= len; // strlen destination + + memcpy((unsigned char *)fac+15,nr,len); + fac[15+len]=0x01; //sending complete + fac[16+len]=0x01; + fac[17+len]=0x80; + + enc_ie_facility(ntmode, msg, fac, 17+len +1 , nt , bc); +} + + +void dec_ie_facility_calldeflect(unsigned char *p, Q931_info_t *qi, unsigned char *fac, int fac_len, unsigned char *cd_nr, int nt, struct misdn_bchannel *bc) +{ + *cd_nr = '\0'; + + if (fac_len >= 15) + { + if (fac[0] != FACILITY_CALLDEFLECT) + return; + if (fac[1] != CALLDEFLECT_ID) + return; + } else { + cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n"); + return ; + } + + + + { + int dest_len=fac[2]-0x0f; + + if (dest_len <0 || dest_len > 15) { + cb_log(1,bc->port, "IE is garbage: FAC_CALLDEFLECT\n"); + return ; + } + + if (fac_len < 15+dest_len) { + cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n"); + return ; + } + + memcpy(cd_nr, &fac[15],dest_len); + cd_nr[dest_len]=0; + + cb_log(5,bc->port, "--> IE CALLDEFLECT NR: %s\n",cd_nr); + } +} + + + +void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc) +{ + switch (type) { + case FACILITY_CENTREX: + { + int setup=0; + enc_ie_facility_centrex(ntmsg, msg, fac.cnip, setup, bc->nt, bc); + } + break; + case FACILITY_CALLDEFLECT: + enc_ie_facility_calldeflect(ntmsg, msg, fac.calldeflect_nr, bc->nt, bc); + break; + default: + cb_log(1,0,"Don't know how handle this facility: %d\n", type); + } +} + +void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc) +{ + int i, fac_len=0; + unsigned char facility[256]; + + if (!bc->nt) + { + p = NULL; + if (qi->QI_ELEMENT(facility)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1; + } + if (!p) + return; + + fac_len = p[0] & 0xff; + + memcpy(facility, p+1, fac_len); + + switch(facility[0]) { + case FACILITY_CENTREX: + { + int cnip_len=15; + + dec_ie_facility_centrex(p, qi,facility, fac_len, fac->cnip, cnip_len, bc->nt, bc); + + *type=FACILITY_CENTREX; + } + break; + case FACILITY_CALLDEFLECT: + dec_ie_facility_calldeflect(p, qi,facility, fac_len, fac->calldeflect_nr, bc->nt, bc); + + *type=FACILITY_CALLDEFLECT; + break; + default: + cb_log(3, bc->port, "Unknown Facility received: "); + i = 0; + while(i < fac_len) + { + cb_log(3, bc->port, " %02x", facility[i]); + i++; + } + cb_log(3, bc->port, " facility\n"); + + *type=FACILITY_NONE; + } + + +} + +/*** FACILITY END **/ + diff --git a/channels/misdn/fac.h b/channels/misdn/fac.h new file mode 100644 index 000000000..acc41f17f --- /dev/null +++ b/channels/misdn/fac.h @@ -0,0 +1,8 @@ +#ifndef FAC_H +#define FAC_H + +void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc); + +void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc); + +#endif diff --git a/channels/misdn/ie.c b/channels/misdn/ie.c index 4d1815f65..a3eb255f8 100644 --- a/channels/misdn/ie.c +++ b/channels/misdn/ie.c @@ -23,17 +23,12 @@ #include <string.h> - -#include "isdn_lib_intern.h" - #include <mISDNuser/mISDNlib.h> #include <mISDNuser/isdn_net.h> #include <mISDNuser/l3dss1.h> #include <mISDNuser/net_l3.h> -#define CENTREX_FAC 0x88 -#define CENTREX_ID 0xa1 #define MISDN_IE_DEBG 0 @@ -69,7 +64,8 @@ void enc_ie_complete(unsigned char **ntmode, msg_t *msg, int complete, int nt, s { *ntmode = p; } else - qi->sending_complete = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(sending_complete) = p - (unsigned char *)qi - sizeof(Q931_info_t); + p[0] = IE_COMPLETE; } } @@ -79,7 +75,7 @@ void dec_ie_complete(unsigned char *p, Q931_info_t *qi, int *complete, int nt, s *complete = 0; if (!nt) { - if (qi->sending_complete) + if (qi->QI_ELEMENT(sending_complete)) *complete = 1; } else if (p) @@ -140,7 +136,7 @@ void enc_ie_bearer(unsigned char **ntmode, msg_t *msg, int coding, int capabilit if (nt) *ntmode = p+1; else - qi->bearer_capability = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(bearer_capability) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_BEARER; p[1] = l; p[2] = 0x80 + (coding<<5) + capability; @@ -166,23 +162,28 @@ void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capabili *stopbits = -1; *dbits = -1; *parity = -1; - + if (!nt) { p = NULL; - if (qi->llc) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->llc + 1; - else if (qi->bearer_capability) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->bearer_capability + 1; +#ifdef LLC_SUPPORT + if (qi->QI_ELEMENT(llc)) { + + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1; + } +#endif + if (qi->QI_ELEMENT(bearer_capability)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1; } if (!p) return; + if (p[0] < 2) { printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]); return; } - + *coding = (p[1]&0x60) >> 5; *capability = p[1] & 0x1f; octet = 2; @@ -292,7 +293,7 @@ void enc_ie_call_id(unsigned char **ntmode, msg_t *msg, unsigned char *callid, i if (nt) *ntmode = p+1; else - qi->call_id = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(call_id) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_CALL_ID; p[1] = l; memcpy(p+2, callid, callid_len); @@ -308,8 +309,8 @@ void dec_ie_call_id(unsigned char *p, Q931_info_t *qi, unsigned char *callid, in if (!nt) { p = NULL; - if (qi->call_id) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->call_id + 1; + if (qi->QI_ELEMENT(call_id)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(call_id) + 1; } if (!p) return; @@ -363,7 +364,7 @@ void enc_ie_called_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, un if (nt) *ntmode = p+1; else - qi->called_nr = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(called_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_CALLED_PN; p[1] = l; p[2] = 0x80 + (type<<4) + plan; @@ -379,8 +380,8 @@ void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, u if (!nt) { p = NULL; - if (qi->called_nr) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->called_nr + 1; + if (qi->QI_ELEMENT(called_nr)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(called_nr) + 1; } if (!p) return; @@ -437,7 +438,7 @@ void enc_ie_calling_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, i if (nt) *ntmode = p+1; else - qi->calling_nr = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(calling_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_CALLING_PN; p[1] = l; if (present >= 0) @@ -465,8 +466,8 @@ void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, if (!nt) { p = NULL; - if (qi->calling_nr) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->calling_nr + 1; + if (qi->QI_ELEMENT(calling_nr)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(calling_nr) + 1; } if (!p) return; @@ -539,7 +540,7 @@ void enc_ie_connected_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, if (nt) *ntmode = p+1; else - qi->connected_nr = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(connected_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_CONNECT_PN; p[1] = l; if (present >= 0) @@ -567,8 +568,8 @@ void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan if (!nt) { p = NULL; - if (qi->connected_nr) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->connected_nr + 1; + if (qi->QI_ELEMENT(connected_nr)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(connected_nr) + 1; } if (!p) return; @@ -624,7 +625,7 @@ void enc_ie_cause(unsigned char **ntmode, msg_t *msg, int location, int cause, i if (nt) *ntmode = p+1; else - qi->cause = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_CAUSE; p[1] = l; p[2] = 0x80 + location; @@ -637,7 +638,7 @@ void enc_ie_cause_standalone(unsigned char **ntmode, msg_t *msg, int location, i if (ntmode) *ntmode = p+1; else - qi->cause = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(cause) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_CAUSE; p[1] = 2; p[2] = 0x80 + location; @@ -653,8 +654,8 @@ void dec_ie_cause(unsigned char *p, Q931_info_t *qi, int *location, int *cause, if (!nt) { p = NULL; - if (qi->cause) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->cause + 1; + if (qi->QI_ELEMENT(cause)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(cause) + 1; } if (!p) return; @@ -705,7 +706,7 @@ void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int ch if (nt) *ntmode = p+1; else - qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_CHANNEL_ID; p[1] = l; if (channel == 0xff) @@ -725,7 +726,7 @@ void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int ch if (nt) *ntmode = p+1; else - qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_CHANNEL_ID; p[1] = l; p[2] = 0x80 + 0x20 + 0x03; @@ -737,7 +738,7 @@ void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int ch if (nt) *ntmode = p+1; else - qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(channel_id) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_CHANNEL_ID; p[1] = l; p[2] = 0x80 + 0x20 + (exclusive<<3) + 0x01; @@ -758,8 +759,8 @@ void dec_ie_channel_id(unsigned char *p, Q931_info_t *qi, int *exclusive, int *c if (!nt) { p = NULL; - if (qi->channel_id) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->channel_id + 1; + if (qi->QI_ELEMENT(channel_id)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(channel_id) + 1; } if (!p) return; @@ -863,7 +864,7 @@ void enc_ie_date(unsigned char **ntmode, msg_t *msg, time_t ti, int nt, struct m if (nt) *ntmode = p+1; else - qi->date = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(date) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_DATE; p[1] = l; p[2] = tm->tm_year % 100; @@ -900,7 +901,7 @@ void enc_ie_display(unsigned char **ntmode, msg_t *msg, unsigned char *display, if (nt) *ntmode = p+1; else - qi->display = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(display) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_DISPLAY; p[1] = l; strncpy((char *)p+2, (char *)display, strlen((char *)display)); @@ -913,8 +914,8 @@ void dec_ie_display(unsigned char *p, Q931_info_t *qi, unsigned char *display, i if (!nt) { p = NULL; - if (qi->display) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->display + 1; + if (qi->QI_ELEMENT(display)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(display) + 1; } if (!p) return; @@ -950,7 +951,7 @@ void enc_ie_keypad(unsigned char **ntmode, msg_t *msg, unsigned char *keypad, in if (nt) *ntmode = p+1; else - qi->keypad = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(keypad) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_KEYPAD; p[1] = l; strncpy((char *)p+2, (char *)keypad, strlen((char *)keypad)); @@ -963,8 +964,8 @@ void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, unsigned char *keypad, int if (!nt) { p = NULL; - if (qi->keypad) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->keypad + 1; + if (qi->QI_ELEMENT(keypad)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(keypad) + 1; } if (!p) return; @@ -1000,7 +1001,7 @@ void enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify, int nt, struc if (nt) *ntmode = p+1; else - qi->notify = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(notify) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_NOTIFY; p[1] = l; p[2] = 0x80 + notify; @@ -1013,8 +1014,8 @@ void dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify, int nt, struc if (!nt) { p = NULL; - if (qi->notify) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->notify + 1; + if (qi->QI_ELEMENT(notify)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(notify) + 1; } if (!p) return; @@ -1060,7 +1061,7 @@ void enc_ie_progress(unsigned char **ntmode, msg_t *msg, int coding, int locatio if (nt) *ntmode = p+1; else - qi->progress = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(progress) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_PROGRESS; p[1] = l; p[2] = 0x80 + (coding<<5) + location; @@ -1077,8 +1078,8 @@ void dec_ie_progress(unsigned char *p, Q931_info_t *qi, int *coding, int *locati if (!nt) { p = NULL; - if (qi->progress) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->progress + 1; + if (qi->QI_ELEMENT(progress)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(progress) + 1; } if (!p) return; @@ -1144,7 +1145,7 @@ void enc_ie_redir_nr(unsigned char **ntmode, msg_t *msg, int type, int plan, int if (nt) *ntmode = p+1; else - qi->redirect_nr = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(redirect_nr) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_REDIR_NR; p[1] = l; if (present >= 0) @@ -1183,8 +1184,8 @@ void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, in if (!nt) { p = NULL; - if (qi->redirect_nr) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redirect_nr + 1; + if (qi->QI_ELEMENT(redirect_nr)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redirect_nr) + 1; } if (!p) return; @@ -1252,7 +1253,7 @@ void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int plan, int *ntmode = p+1; else /* #warning REINSERT redir_dn, when included in te-mode */ - /*qi->redir_dn = p - (unsigned char *)qi - sizeof(Q931_info_t)*/; + /*qi->QI_ELEMENT(redir_dn) = p - (unsigned char *)qi - sizeof(Q931_info_t)*/; p[0] = IE_REDIR_DN; p[1] = l; if (present >= 0) @@ -1280,8 +1281,8 @@ void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, in { p = NULL; /* #warning REINSERT redir_dn, when included in te-mode */ -/* if (qi->redir_dn) */ -/* p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redir_dn + 1; */ +/* if (qi->QI_ELEMENT(redir_dn)) */ +/* p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redir_dn) + 1; */ } if (!p) return; @@ -1306,242 +1307,6 @@ void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, in } -/* IE_FACILITY */ -void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc) -{ - unsigned char *p; - Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN); - int l; - - char debug[768]; - int i; - - if (!facility || facility_len<=0) - { - return; - } - - i = 0; - while(i < facility_len) - { - if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", facility[i]); - i++; - } - - if (MISDN_IE_DEBG) printf(" facility%s\n", debug); - - l = facility_len; - p = msg_put(msg, l+2); - if (nt) - *ntmode = p+1; - else - qi->facility = p - (unsigned char *)qi - sizeof(Q931_info_t); - p[0] = IE_FACILITY; - p[1] = l; - memcpy(p+2, facility, facility_len); -} - -void dec_ie_facility(unsigned char *p, Q931_info_t *qi, unsigned char *facility, int *facility_len, int nt, struct misdn_bchannel *bc) -{ - int i; - struct misdn_stack *stack=get_stack_by_bc(bc); - - *facility_len = 0; - - if (!nt) - { - p = NULL; - if (qi->facility) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->facility + 1; - } - if (!p) - return; - - *facility_len = p[0]; - memcpy(facility, p+1, *facility_len); - - i = 0; - while(i < *facility_len) - { - cb_log(3, stack->port, " %02x", facility[i]); - i++; - } - cb_log(3, stack->port, " facility\n"); -} - - -/* facility for siemens CENTEX (known parts implemented only) */ -void enc_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc) -{ - unsigned char centrex[256]; - int i = 0; - - if (!cnip) - return; - - /* centrex facility */ - centrex[i++] = CENTREX_FAC; - centrex[i++] = CENTREX_ID; - - /* cnip */ - if (strlen((char *)cnip) > 15) - { -/* if (options.deb & DEBUG_PORT) */ - if (MISDN_IE_DEBG) printf("%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__); - cnip[15] = '\0'; - } - /* dunno what the 8 bytes mean */ - if (setup) - { - centrex[i++] = 0x17; - centrex[i++] = 0x02; - centrex[i++] = 0x02; - centrex[i++] = 0x44; - centrex[i++] = 0x18; - centrex[i++] = 0x02; - centrex[i++] = 0x01; - centrex[i++] = 0x09; - } else - { - centrex[i++] = 0x18; - centrex[i++] = 0x02; - centrex[i++] = 0x02; - centrex[i++] = 0x81; - centrex[i++] = 0x09; - centrex[i++] = 0x02; - centrex[i++] = 0x01; - centrex[i++] = 0x0a; - } - - centrex[i++] = 0x80; - centrex[i++] = strlen((char *)cnip); - strcpy((char *)(¢rex[i]), (char *)cnip); - i += strlen((char *)cnip); - if (MISDN_IE_DEBG) printf(" cnip='%s'\n", cnip); - - /* encode facility */ - enc_ie_facility(ntmode, msg, centrex, i, nt , bc); -} - -void dec_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *cnip, int cnip_len, int nt, struct misdn_bchannel *bc) -{ - unsigned char centrex[256]; - char debug[768]; - int facility_len = 0; - int i = 0, j; - *cnip = '\0'; - - dec_ie_facility(p, qi, centrex, &facility_len, nt, bc); - if (facility_len >= 2) - { - if (centrex[i++] != CENTREX_FAC) - return; - if (centrex[i++] != CENTREX_ID) - return; - } - - /* loop sub IEs of facility */ - while(facility_len > i+1) - { - if (centrex[i+1]+i+1 > facility_len) - { - printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__); - return; - } - switch(centrex[i]) - { - case 0x80: - strnncpy(cnip, ¢rex[i+2], centrex[i+1], cnip_len); - if (MISDN_IE_DEBG) printf(" CENTREX cnip='%s'\n", cnip); - break; - - default: - j = 0; - while(j < centrex[i+1]) - { - if (MISDN_IE_DEBG) printf(debug+(j*3), " %02x", centrex[i+1+j]); - i++; - } - if (MISDN_IE_DEBG) printf(" CENTREX unknown=0x%2x len=%d%s\n", centrex[i], centrex[i+1], debug); - } - i += 1+centrex[i+1]; - } -} - - - - -/* facility for siemens CENTEX (known parts implemented only) */ -void enc_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc) -{ - unsigned char fac[256]; - - if (!nr) - return; - - /* calldeflect facility */ - - /* cnip */ - if (strlen((char *)nr) > 15) - { -/* if (options.deb & DEBUG_PORT) */ - if (MISDN_IE_DEBG) printf("%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__); - nr[15] = '\0'; - } - - fac[0]=0; // len - fac[1]=0; //len - fac[2]=0x01; // Use D-Chan - fac[3]=0; // Keypad len - fac[4]=31; // user user data? len = 31 = 29 + 2 - fac[5]=0x1c; // magic? - fac[6]=0x1d; // strlen destination + 18 = 29 - fac[7]=0x91; // .. - fac[8]=0xA1; - fac[9]=0x1A; // strlen destination + 15 = 26 - fac[10]=0x02; - fac[11]=0x01; - fac[12]=0x70; - fac[13]=0x02; - fac[14]=0x01; - fac[15]=0x0d; - fac[16]=0x30; - fac[17]=0x12; // strlen destination + 7 = 18 - fac[18]=0x30; // ...hm 0x30 - fac[19]=0x0d; // strlen destination + 2 - fac[20]=0x80; // CLIP - fac[21]=0x0b; // strlen destination - fac[22]=0x01; // destination start - fac[23]=0x01; // - fac[24]=0x01; // - fac[25]=0x01; // - fac[26]=0x01; // - fac[27]=0x01; // - fac[28]=0x01; // - fac[29]=0x01; // - fac[30]=0x01; // - fac[31]=0x01; // - fac[32]=0x01; // - fac[33]=0x01; // 0x1 = sending complete - fac[34]=0x01; - fac[35]=0x01; - - memcpy((unsigned char *)fac+22,nr,strlen(nr)); - fac[22+strlen( nr)]=0x01; // fill with 0x01 if number is only 6 numbers (local call) - fac[23+strlen(nr)]=0x01; - fac[24+strlen(nr)]=0x01; - fac[25+strlen(nr)]=0x01; - fac[26+strlen(nr)]=0x01; - - fac[6]=18+strlen(nr); - fac[9]=15+strlen(nr); - fac[17]=7+strlen(nr); - fac[19]=2+strlen(nr); - fac[21]=strlen(nr); - - enc_ie_facility(ntmode, msg, &fac[4], 36-4, nt , bc); -} - /* IE_USERUSER */ void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, unsigned char *user, int user_len, int nt, struct misdn_bchannel *bc) @@ -1577,7 +1342,7 @@ void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, unsigned if (nt) *ntmode = p+1; else - qi->useruser = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(useruser) = p - (unsigned char *)qi - sizeof(Q931_info_t); p[0] = IE_USER_USER; p[1] = l; p[2] = 0x80 + protocol; @@ -1595,8 +1360,8 @@ void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, unsigned if (!nt) { p = NULL; - if (qi->useruser) - p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->useruser + 1; + if (qi->QI_ELEMENT(useruser)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(useruser) + 1; } if (!p) return; @@ -1619,3 +1384,5 @@ void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, unsigned } + + diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c index aa1d51cea..ea7c20849 100644 --- a/channels/misdn/isdn_lib.c +++ b/channels/misdn/isdn_lib.c @@ -11,31 +11,56 @@ * the GNU General Public License */ + +#include <syslog.h> #include "isdn_lib_intern.h" +#include <mISDNuser/isdn_debug.h> +void misdn_join_conf(struct misdn_bchannel *bc, int conf_id); +void misdn_split_conf(struct misdn_bchannel *bc, int conf_id); -int misdn_ibuf_freecount(void *buf) -{ - return ibuf_freecount( (ibuffer_t*)buf); -} +int queue_cleanup_bc(struct misdn_bchannel *bc) ; -int misdn_ibuf_usedcount(void *buf) -{ - return ibuf_usedcount( (ibuffer_t*)buf); -} +int misdn_lib_get_l2_up(struct misdn_stack *stack); -void misdn_ibuf_memcpy_r(char *to, void *buf, int len) +struct misdn_stack* get_misdn_stack( void ); + +int misdn_lib_port_block(int port) { - ibuf_memcpy_r( to, (ibuffer_t*)buf, len); + struct misdn_stack *stack=get_misdn_stack(); + for ( ; stack; stack=stack->next) { + if (stack->port == port) { + stack->blocked=1; + return 0; + } + } + return -1; + } -void misdn_ibuf_memcpy_w(void *buf, char *from, int len) +int misdn_lib_port_unblock(int port) { - ibuf_memcpy_w((ibuffer_t*)buf, from, len); -} + struct misdn_stack *stack=get_misdn_stack(); + for ( ; stack; stack=stack->next) { + if (stack->port == port) { + stack->blocked=0; + return 0; + } + } + return -1; -struct misdn_stack* get_misdn_stack( void ); +} +int misdn_lib_is_port_blocked(int port) +{ + struct misdn_stack *stack=get_misdn_stack(); + for ( ; stack; stack=stack->next) { + if (stack->port == port) { + return stack->blocked; + } + } + return -1; +} int misdn_lib_is_ptp(int port) { @@ -46,6 +71,20 @@ int misdn_lib_is_ptp(int port) return -1; } +int misdn_lib_get_maxchans(int port) +{ + struct misdn_stack *stack=get_misdn_stack(); + for ( ; stack; stack=stack->next) { + if (stack->port == port) { + if (stack->pri) + return 30; + else + return 2; + } + } + return -1; +} + struct misdn_stack* get_stack_by_bc(struct misdn_bchannel *bc) { @@ -73,7 +112,8 @@ void get_show_stack_details(int port, char *buf) } if (stack) { - sprintf(buf, "* Stack Addr: Port %d Type %s Prot. %s L2Link %s L1Link:%s", stack->upper_id & IF_CONTRMASK, stack->mode==NT_MODE?"NT":"TE", stack->ptp?"PTP":"PMP", stack->l2link?"UP":"DOWN", stack->l1link?"UP":"DOWN"); + sprintf(buf, "* Port %d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d", stack->port, stack->nt?"NT":"TE", stack->ptp?"PTP":"PMP", stack->l2link?"UP":"DOWN", stack->l1link?"UP":"DOWN",stack->blocked); + } else { buf[0]=0; } @@ -125,6 +165,8 @@ struct misdn_lib { #define MISDN_DEBUG 0 +void misdn_tx_jitter(struct misdn_bchannel *bc, int len); + struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long l3id); int setup_bc(struct misdn_bchannel *bc); @@ -165,14 +207,13 @@ struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned lon /* from isdn_lib.h */ int init_bc(struct misdn_stack * stack, struct misdn_bchannel *bc, int midev, int port, int bidx, char *msn, int firsttime); -struct misdn_stack* stack_te_init(int midev, int port, int ptp); -void stack_te_destroy(struct misdn_stack* stack); +struct misdn_stack* stack_init(int midev, int port, int ptp); +void stack_destroy(struct misdn_stack* stack); /* user iface */ int te_lib_init( void ) ; /* returns midev */ void te_lib_destroy(int midev) ; struct misdn_bchannel *manager_find_bc_by_pid(int pid); struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc); -unsigned char * manager_flip_buf_bits ( unsigned char * buf , int len); void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c2_len); void manager_clean_bc(struct misdn_bchannel *bc ); void manager_bchannel_setup (struct misdn_bchannel *bc); @@ -234,7 +275,7 @@ void init_flip_bits(void) } } -static unsigned char * flip_buf_bits ( unsigned char * buf , int len) +unsigned char * flip_buf_bits ( unsigned char * buf , int len) { int i; char * start = buf; @@ -315,21 +356,27 @@ int send_msg (int midev, struct misdn_bchannel *bc, msg_t *dmsg) iframe_t *frm; frm = (iframe_t *)dmsg->data; struct misdn_stack *stack=get_stack_by_bc(bc); + + if (!stack) { + cb_log(0,bc->port,"send_msg: IEK!! no stack\n "); + return -1; + } - frm->addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ; + frm->addr = (stack->upper_id | FLG_MSG_DOWN); frm->dinfo = bc->l3_id; - frm->len = (dmsg->len) - mISDN_HEADER_LEN; - + + cb_log(4,stack->port,"Sending msg, prim:%x addr:%x dinfo:%x\n",frm->prim,frm->addr,frm->dinfo); + mISDN_write(midev, dmsg->data, dmsg->len, TIMEOUT_1SEC); - free_msg(dmsg); return 0; } -static int mypid=0; +static int mypid=1; + int misdn_cap_is_speech(int cap) /** Poor mans version **/ @@ -362,7 +409,7 @@ void dump_chan_list(struct misdn_stack *stack) int i; for (i=0; i <stack->b_num; i++) { - cb_log(3, stack->port, "Idx:%d stack->cchan:%d Chan:%d\n",i,stack->channels[i], i+1); + cb_log(6, stack->port, "Idx:%d stack->cchan:%d Chan:%d\n",i,stack->channels[i], i+1); } } @@ -373,8 +420,10 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, int channel) { int i; + cb_log(1,stack->port,"find_free_chan: req_chan:%d\n",channel); + if (channel < 0 || channel > MAX_BCHANS) { - cb_log(4, stack->port, " !! out of bound call to find_free_chan_in_stack! (port:%d ch:%d)\n", stack->port, channel); + cb_log(4, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel); return 0; } @@ -383,7 +432,7 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, int channel) for (i = 0; i < stack->b_num; i++) { if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 Dchannel ;) and work with chan preselection */ if (!stack->channels[i]) { - cb_log (4, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1); + cb_log (1, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1); stack->channels[i] = 1; return i+1; } @@ -398,24 +447,96 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, int channel) int empty_chan_in_stack(struct misdn_stack *stack, int channel) { - cb_log (4, stack?stack->port:0, " --> empty chan %d\n",channel); + if (channel<=0) { + cb_log(0,stack?stack->port:0, "empty_chan_inst_stack: cannot empty channel %d\n",channel); + return -1; + } + + cb_log (4, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel); stack->channels[channel-1] = 0; dump_chan_list(stack); return 0; } +char *bc_state2str(enum bchannel_state state) { + int i; + + struct bchan_state_s { + char *n; + enum bchannel_state s; + } states[] = { + {"BCHAN_CLEANED", BCHAN_CLEANED }, + {"BCHAN_EMPTY", BCHAN_EMPTY}, + {"BCHAN_SETUP", BCHAN_SETUP}, + {"BCHAN_SETUPED", BCHAN_SETUPED}, + {"BCHAN_ACTIVE", BCHAN_ACTIVE}, + {"BCHAN_ACTIVATED", BCHAN_ACTIVATED}, + {"BCHAN_BRIDGE", BCHAN_BRIDGE}, + {"BCHAN_BRIDGED", BCHAN_BRIDGED}, + {"BCHAN_RELEASE", BCHAN_RELEASE}, + {"BCHAN_RELEASED", BCHAN_RELEASED}, + {"BCHAN_CLEAN", BCHAN_CLEAN}, + {"BCHAN_CLEAN_REQUEST", BCHAN_CLEAN_REQUEST}, + {"BCHAN_ERROR", BCHAN_ERROR} + }; + + for (i=0; i< sizeof(states)/sizeof(struct bchan_state_s); i++) + if ( states[i].s == state) + return states[i].n; + + return "UNKNOWN"; +} + +void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state) +{ + cb_log(5,bc->port,"BC_STATE_CHANGE: from:%s to:%s\n", + bc_state2str(bc->bc_state), + bc_state2str(state) ); + + switch (state) { + case BCHAN_ACTIVATED: + if (bc->next_bc_state == BCHAN_BRIDGED) { + misdn_join_conf(bc, bc->conf_id); + bc->next_bc_state = BCHAN_EMPTY; + return; + } + default: + bc->bc_state=state; + break; + } +} + +void bc_next_state_change(struct misdn_bchannel *bc, enum bchannel_state state) +{ + cb_log(5,bc->port,"BC_NEXT_STATE_CHANGE: from:%s to:%s\n", + bc_state2str(bc->next_bc_state), + bc_state2str(state) ); + + bc->next_bc_state=state; +} + void empty_bc(struct misdn_bchannel *bc) { - bc->state=STATE_NOTHING; + bc->bframe_len=0; + + bc->in_use= 0; + bc->channel = 0; - bc->in_use = 0; + bc->sending_complete = 0; + + bc->restart_channel=0; + + bc->conf_id = 0; + + bc->need_more_infos = 0; + bc->send_dtmf=0; bc->nodsp=0; bc->nojitter=0; - + bc->time_usec=0; bc->rxgain=0; @@ -426,12 +547,13 @@ void empty_bc(struct misdn_bchannel *bc) bc->crypt_key[0] = 0; - bc->tone=TONE_NONE; - bc->tone_cnt2 = bc->tone_cnt=0; + bc->generate_tone=0; + bc->tone_cnt=0; bc->dnumplan=NUMPLAN_UNKNOWN; bc->onumplan=NUMPLAN_UNKNOWN; bc->rnumplan=NUMPLAN_UNKNOWN; + bc->cpnnumplan=NUMPLAN_UNKNOWN; bc->active = 0; @@ -441,8 +563,10 @@ void empty_bc(struct misdn_bchannel *bc) bc->ec_enable = 0; bc->ec_deftaps = 128; bc->ec_whenbridged = 0; + +#ifdef EC_TRAIN bc->ec_training = 1; - +#endif bc->orig=0; @@ -460,24 +584,28 @@ void empty_bc(struct misdn_bchannel *bc) bc->capability=INFO_CAPABILITY_SPEECH; bc->law=INFO_CODEC_ALAW; bc->mode=0; - bc->rate=0; + bc->rate=0x10; bc->user1=0; - bc->async=0; bc->urate=0; + bc->hdlc=0; bc->info_dad[0] = 0; bc->display[0] = 0; bc->infos_pending[0] = 0; + bc->cad[0] = 0; bc->oad[0] = 0; bc->dad[0] = 0; + bc->rad[0] = 0; bc->orig_dad[0] = 0; - bc->facility=FACILITY_NONE; - bc->facility_calldeflect_nr[0]=0; - + bc->fac_type=FACILITY_NONE; + bc->out_fac_type=FACILITY_NONE; + bc->te_choose_channel = 0; + + bc->holded_bc=NULL; } @@ -486,29 +614,38 @@ int clean_up_bc(struct misdn_bchannel *bc) int ret=0; unsigned char buff[32]; struct misdn_stack * stack; + + cb_log(3, bc?bc->port:0, "$$$ CLEANUP CALLED pid:%d\n", bc?bc->pid:-1); if (!bc ) return -1; stack=get_stack_by_bc(bc); + if (!stack) return -1; - if (!bc->upset) { + switch (bc->bc_state ) { + case BCHAN_CLEANED: cb_log(5, stack->port, "$$$ Already cleaned up bc with stid :%x\n", bc->b_stid); return -1; + + default: + break; } - - cb_log(5, stack->port, "$$$ Cleaning up bc with stid :%x\n", bc->b_stid); - - if ( misdn_cap_is_speech(bc->capability) && bc->ec_enable) { - manager_ec_disable(bc); - } + cb_log(2, stack->port, "$$$ Cleaning up bc with stid :%x pid:%d\n", bc->b_stid, bc->pid); - mISDN_write_frame(stack->midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + manager_bchannel_deactivate(bc); + + + manager_ec_disable(bc); + + + mISDN_write_frame(stack->midev, buff, bc->layer_id|FLG_MSG_TARGET|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + /*mISDN_clear_stack(stack->midev, bc->b_stid);*/ + bc->b_stid = 0; - - bc->upset=0; + bc_state_change(bc, BCHAN_CLEANED); return ret; } @@ -518,13 +655,13 @@ int clean_up_bc(struct misdn_bchannel *bc) void clear_l3(struct misdn_stack *stack) { int i; + for (i=0; i<stack->b_num; i++) { if (global_state == MISDN_INITIALIZED) { - cb_event(EVENT_CLEANUP, &stack->bc[i], glob_mgr->user_data); + cb_event(EVENT_CLEANUP, &stack->bc[i], NULL); empty_chan_in_stack(stack,i+1); empty_bc(&stack->bc[i]); clean_up_bc(&stack->bc[i]); - } } @@ -532,7 +669,13 @@ void clear_l3(struct misdn_stack *stack) int set_chan_in_stack(struct misdn_stack *stack, int channel) { - stack->channels[channel-1] = 1; + + cb_log(4,stack->port,"set_chan_in_stack: %d\n",channel); + if (channel >=1 ) { + stack->channels[channel-1] = 1; + } else { + cb_log(0,stack->port,"couldn't set channel %d in\n", channel ); + } return 0; } @@ -549,19 +692,59 @@ int chan_in_stack_free(struct misdn_stack *stack, int channel) static int newteid=0; -#ifdef MISDNUSER_JOLLY #define MAXPROCS 0x100 -#else -#define MAXPROCS 0x10 -#endif + +int misdn_lib_get_l1_down(struct misdn_stack *stack) +{ + /* Pull Up L1 */ + iframe_t act; + act.prim = PH_DEACTIVATE | REQUEST; + act.addr = (stack->upper_id | FLG_MSG_DOWN) ; + + + act.dinfo = 0; + act.len = 0; + + return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC); + + +} + + +int misdn_lib_get_l2_down(struct misdn_stack *stack) +{ + + if (stack->ptp && (stack->nt) ) { + msg_t *dmsg; + /* L2 */ + dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0); + + if (stack->nst.manager_l3(&stack->nst, dmsg)) + free_msg(dmsg); + + } else { + iframe_t act; + + act.prim = DL_RELEASE| REQUEST; + act.addr = (stack->upper_id |FLG_MSG_DOWN) ; + + act.dinfo = 0; + act.len = 0; + return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC); + } + + return 0; +} int misdn_lib_get_l1_up(struct misdn_stack *stack) { - /* Pull Up L1 if we have JOLLY */ + /* Pull Up L1 */ iframe_t act; act.prim = PH_ACTIVATE | REQUEST; - act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ; + act.addr = (stack->upper_id | FLG_MSG_DOWN) ; + + act.dinfo = 0; act.len = 0; @@ -572,7 +755,7 @@ int misdn_lib_get_l1_up(struct misdn_stack *stack) int misdn_lib_get_l2_up(struct misdn_stack *stack) { - if (stack->ptp && (stack->mode == NT_MODE) ) { + if (stack->ptp && (stack->nt) ) { msg_t *dmsg; /* L2 */ dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0); @@ -584,8 +767,8 @@ int misdn_lib_get_l2_up(struct misdn_stack *stack) iframe_t act; act.prim = DL_ESTABLISH | REQUEST; - - act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN; + act.addr = (stack->upper_id |FLG_MSG_DOWN) ; + act.dinfo = 0; act.len = 0; return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC); @@ -594,23 +777,37 @@ int misdn_lib_get_l2_up(struct misdn_stack *stack) return 0; } - -int misdn_lib_get_l2_status(struct misdn_stack *stack) +int misdn_lib_get_l2_te_ptp_up(struct misdn_stack *stack) { iframe_t act; - -#ifdef DL_STATUS - act.prim = DL_STATUS | REQUEST; -#else + act.prim = DL_ESTABLISH | REQUEST; -#endif - act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN; + act.addr = (stack->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN; + act.dinfo = 0; act.len = 0; return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC); + return 0; } +int misdn_lib_get_short_status(struct misdn_stack *stack) +{ + iframe_t act; + + + act.prim = MGR_SHORTSTATUS | REQUEST; + + act.addr = (stack->upper_id | MSG_BROADCAST) ; + + act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL; + + act.len = 0; + return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC); +} + + + static int create_process (int midev, struct misdn_bchannel *bc) { iframe_t ncr; int l3_id; @@ -618,35 +815,32 @@ static int create_process (int midev, struct misdn_bchannel *bc) { struct misdn_stack *stack=get_stack_by_bc(bc); int free_chan; - if (stack->mode == NT_MODE) { + if (stack->nt) { free_chan = find_free_chan_in_stack(stack, bc->channel_preselected?bc->channel:0); if (!free_chan) return -1; bc->channel=free_chan; + + cb_log(4,stack->port, " --> found channel: %d\n",free_chan); for (i=0; i <= MAXPROCS; i++) if (stack->procids[i]==0) break; if (i== MAXPROCS) { - cb_log(0, stack->port, "Couldnt Create New ProcId Port:%d\n",stack->port); + cb_log(0, stack->port, "Couldnt Create New ProcId.\n"); return -1; } stack->procids[i]=1; -#ifdef MISDNUSER_JOLLY l3_id = 0xff00 | i; -#else - l3_id = 0xfff0 | i; -#endif ncr.prim = CC_NEW_CR | REQUEST; - ncr.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ; + + ncr.addr = (stack->upper_id | FLG_MSG_DOWN) ; + ncr.dinfo = l3_id; ncr.len = 0; bc->l3_id = l3_id; - if (mypid>5000) mypid=0; - bc->pid=mypid++; - cb_log(3, stack->port, " --> new_l3id %x\n",l3_id); } else { @@ -655,6 +849,7 @@ static int create_process (int midev, struct misdn_bchannel *bc) { free_chan = find_free_chan_in_stack(stack, bc->channel_preselected?bc->channel:0); if (!free_chan) return -1; bc->channel=free_chan; + cb_log(2,stack->port, " --> found channel: %d\n",free_chan); } else { /* other phones could have made a call also on this port (ptmp) */ bc->channel=0xff; @@ -668,15 +863,14 @@ static int create_process (int midev, struct misdn_bchannel *bc) { l3_id = (entity<<16) | newteid; /* preparing message */ ncr.prim = CC_NEW_CR | REQUEST; - ncr.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ; + + ncr.addr = (stack->upper_id | FLG_MSG_DOWN) ; + ncr.dinfo =l3_id; ncr.len = 0; /* send message */ bc->l3_id = l3_id; - if (mypid>5000) mypid=0; - bc->pid=mypid++; - cb_log(3, stack->port, "--> new_l3id %x\n",l3_id); mISDN_write(midev, &ncr, mISDN_HEADER_LEN+ncr.len, TIMEOUT_1SEC); @@ -698,34 +892,38 @@ int setup_bc(struct misdn_bchannel *bc) mISDN_pid_t pid; int ret; + struct misdn_stack *stack=get_stack_by_bc(bc); + + if (!stack) { + cb_log(0, bc->port, "setup_bc: NO STACK FOUND!!\n"); + return -1; + } int midev=stack->midev; int channel=bc->channel-1-(bc->channel>16); int b_stid=stack->b_stids[channel>=0?channel:0]; - - if (bc->nodsp ) - clean_up_bc(bc); - - if ( !misdn_cap_is_speech(bc->capability)) - clean_up_bc(bc); - - - if (bc->upset) { - cb_log(4, stack->port, "$$$ bc already upsetted stid :%x\n", b_stid); - return -1; + + switch (bc->bc_state) { + case BCHAN_CLEANED: + break; + default: + cb_log(4, stack->port, "$$$ bc already upsetted stid :%x (state:%s)\n", b_stid, bc_state2str(bc->bc_state) ); + return -1; } cb_log(5, stack->port, "$$$ Setting up bc with stid :%x\n", b_stid); if (b_stid <= 0) { - cb_log(0, stack->port," -- Stid <=0 at the moment on port:%d channel:%d\n",stack->port,channel); + cb_log(0, stack->port," -- Stid <=0 at the moment in channel:%d\n",channel); + + bc_state_change(bc,BCHAN_ERROR); return 1; } - + bc->b_stid = b_stid; { @@ -738,78 +936,117 @@ int setup_bc(struct misdn_bchannel *bc) li.st = bc->b_stid; /* given idx */ - if ( misdn_cap_is_speech(bc->capability) && !bc->nodsp && bc->async != 1) { - cb_log(4, stack->port,"setup_bc: with dsp\n"); +#define MISDN_DSP +#ifndef MISDN_DSP + bc->nodsp=1; +#endif + if ( bc->hdlc || bc->nodsp) { + cb_log(4, stack->port,"setup_bc: without dsp\n"); { int l = sizeof(li.name); - strncpy(li.name, "B L4", l); + strncpy(li.name, "B L3", l); li.name[l-1] = 0; } - li.pid.layermask = ISDN_LAYER((4)); - li.pid.protocol[4] = ISDN_PID_L4_B_USER; + li.pid.layermask = ISDN_LAYER((3)); + li.pid.protocol[3] = ISDN_PID_L3_B_USER; + bc->layer=3; } else { - cb_log(4, stack->port,"setup_bc: without dsp\n"); + cb_log(4, stack->port,"setup_bc: with dsp\n"); { int l = sizeof(li.name); - strncpy(li.name, "B L3", l); + strncpy(li.name, "B L4", l); li.name[l-1] = 0; } - li.pid.layermask = ISDN_LAYER((3)); - li.pid.protocol[3] = ISDN_PID_L3_B_USER; - } + li.pid.layermask = ISDN_LAYER((4)); + li.pid.protocol[4] = ISDN_PID_L4_B_USER +; + bc->layer=4; + + } ret = mISDN_new_layer(midev, &li); - if (ret <= 0) { - cb_log(0, stack->port,"New Layer Err: %d %s port:%d\n",ret,strerror(errno), stack->port); + if (ret ) { + cb_log(0, stack->port,"New Layer Err: %d %s\n",ret,strerror(errno)); + + bc_state_change(bc,BCHAN_ERROR); return(-EINVAL); } - - bc->layer_id = ret; + + bc->layer_id = li.id; } memset(&pid, 0, sizeof(pid)); - bc->addr = ( bc->layer_id & IF_ADDRMASK) | IF_DOWN; - cb_log(4, stack->port," --> Got Adr %x\n", bc->addr); - cb_log(4, stack->port," --> Channel is %d\n", bc->channel); - if (bc->async == 1 || bc->nodsp) { - cb_log(4, stack->port," --> TRANSPARENT Mode (no DSP, no HDLC)\n"); + cb_log(4, stack->port," --> Channel is %d\n", bc->channel); + + if (bc->nodsp) { + cb_log(2, stack->port," --> TRANSPARENT Mode (no DSP, no HDLC)\n"); pid.protocol[1] = ISDN_PID_L1_B_64TRANS; pid.protocol[2] = ISDN_PID_L2_B_TRANS; pid.protocol[3] = ISDN_PID_L3_B_USER; pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)); - } else if ( misdn_cap_is_speech(bc->capability)) { - cb_log(4, stack->port," --> TRANSPARENT Mode\n"); + } else if ( bc->hdlc ) { + cb_log(2, stack->port," --> HDLC Mode\n"); +#ifdef ACK_HDLC + bc->ack_hdlc=(sem_t*)malloc(sizeof(sem_t)); + if ( sem_init((sem_t*)bc->ack_hdlc, 1, 0)<0 ) + sem_init((sem_t*)bc->ack_hdlc, 0, 0); +#endif + + pid.protocol[1] = ISDN_PID_L1_B_64HDLC ; + pid.protocol[2] = ISDN_PID_L2_B_TRANS ; + pid.protocol[3] = ISDN_PID_L3_B_USER; + pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) ; + } else { + cb_log(2, stack->port," --> TRANSPARENT Mode\n"); pid.protocol[1] = ISDN_PID_L1_B_64TRANS; pid.protocol[2] = ISDN_PID_L2_B_TRANS; pid.protocol[3] = ISDN_PID_L3_B_DSP; pid.protocol[4] = ISDN_PID_L4_B_USER; pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4)); - } else { - cb_log(4, stack->port," --> HDLC Mode\n"); - pid.protocol[1] = ISDN_PID_L1_B_64HDLC ; - pid.protocol[2] = ISDN_PID_L2_B_TRANS ; - pid.protocol[3] = ISDN_PID_L3_B_USER; - pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) ; - } - + } + ret = mISDN_set_stack(midev, bc->b_stid, &pid); - - + if (ret){ - cb_log(5, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno)); - - mISDN_write_frame(midev, buff, bc->addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + cb_log(0, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno)); + + mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + + bc_state_change(bc,BCHAN_ERROR); return(-EINVAL); } - - bc->upset=1; - + + ret = mISDN_get_setstack_ind(midev, bc->layer_id); + + if (ret) { + cb_log(0, stack->port,"$$$ Set StackIND Err: %d %s\n",ret,strerror(errno)); + mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + + bc_state_change(bc,BCHAN_ERROR); + return(-EINVAL); + } + + ret = mISDN_get_layerid(midev, bc->b_stid, bc->layer) ; + + bc->addr = ret>0? ret : 0; + + if (!bc->addr) { + cb_log(0, stack->port,"$$$ Get Layerid Err: %d %s\n",ret,strerror(errno)); + mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + + bc_state_change(bc,BCHAN_ERROR); + } + + manager_bchannel_activate(bc); + + bc_state_change(bc,BCHAN_ACTIVATED); + return 0; } @@ -824,7 +1061,7 @@ int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, in if (!bc) return -1; - cb_log(4, port, "Init.BC %d on port:%d\n",bidx, port); + cb_log(8, port, "Init.BC %d.\n",bidx); memset(bc, 0,sizeof(struct misdn_bchannel)); @@ -836,30 +1073,24 @@ int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, in empty_bc(bc); - bc->upset=0; + bc_state_change(bc, BCHAN_CLEANED); + bc->port=stack->port; - bc->nt=stack->mode==NT_MODE?1:0; + bc->nt=stack->nt?1:0; { ibuffer_t* ibuf= init_ibuffer(MISDN_IBUF_SIZE); - ibuffer_t* mbuf= init_ibuffer(MISDN_IBUF_SIZE); if (!ibuf) return -1; - if (!mbuf) return -1; clear_ibuffer( ibuf); - clear_ibuffer( mbuf); ibuf->rsem=malloc(sizeof(sem_t)); - mbuf->rsem=malloc(sizeof(sem_t)); bc->astbuf=ibuf; - bc->misdnbuf=mbuf; if (sem_init(ibuf->rsem,1,0)<0) sem_init(ibuf->rsem,0,0); - if (sem_init(mbuf->rsem,1,0)< 0) - sem_init(mbuf->rsem,0,0); } @@ -870,13 +1101,13 @@ int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, in stack_info_t *stinf; ret = mISDN_get_stack_info(midev, stack->port, buff, sizeof(buff)); if (ret < 0) { - cb_log(0, port, "%s: Cannot get stack info for port:%d (ret=%d)\n", __FUNCTION__, port, ret); + cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret); return -1; } stinf = (stack_info_t *)&frm->data.p; - cb_log(4, port, " --> Child %x\n",stinf->child[bidx]); + cb_log(8, port, " --> Child %x\n",stinf->child[bidx]); } return 0; @@ -884,98 +1115,7 @@ int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, in -struct misdn_stack * stack_nt_init(struct misdn_stack *stack, int midev, int port) -{ - int ret; - layer_info_t li; - interface_info_t ii; - - - cb_log(4, port, "Init. Stack on port:%d\n",port); - stack->mode = NT_MODE; - - stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, 1); - if (stack->lower_id <= 0) { - cb_log(0, port, "%s: Cannot get layer(%d) id of port:%d\n", __FUNCTION__, 1, port); - return(NULL); - } - - - memset(&li, 0, sizeof(li)); - { - int l = sizeof(li.name); - strncpy(li.name,"net l2", l); - li.name[l-1] = 0; - } - li.object_id = -1; - li.extentions = 0; - li.pid.protocol[2] = ISDN_PID_L2_LAPD_NET; - li.pid.layermask = ISDN_LAYER((2)); - li.st = stack->d_stid; - - - stack->upper_id = mISDN_new_layer(midev, &li); - if (stack->upper_id <= 0) { - cb_log(0, port, "%s: Cannot add layer %d of port:%d\n", __FUNCTION__, 2, port); - return(NULL); - } - - cb_log(4, port, "NT Stacks upper_id %x\n",stack->upper_id); - - memset(&ii, 0, sizeof(ii)); - ii.extentions = EXT_IF_EXCLUSIV; - ii.owner = stack->upper_id; - ii.peer = stack->lower_id; - ii.stat = IF_DOWN; - ret = mISDN_connect(midev, &ii); - if (ret) { - cb_log(0, port, "%s: Cannot connect layer %d of port:%d exclusively.\n", __FUNCTION__, 2, port); - return(NULL); - } - - /* create nst (nt-mode only) */ - { - memset(&stack->nst, 0, sizeof(net_stack_t)); - memset(&stack->mgr, 0, sizeof(manager_t)); - - stack->mgr.nst = &stack->nst; - stack->nst.manager = &stack->mgr; - - stack->nst.l3_manager = handle_event_nt; - stack->nst.device = midev; - stack->nst.cardnr = port; - stack->nst.d_stid = stack->d_stid; - -#ifdef MISDNUSER_JOLLY - stack->nst.feature = FEATURE_NET_HOLD; - if (stack->ptp) - stack->nst.feature |= FEATURE_NET_PTP; - if (stack->pri) - stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID; -#endif - - stack->nst.l1_id = stack->lower_id; - stack->nst.l2_id = stack->upper_id; - - msg_queue_init(&stack->nst.down_queue); - - Isdnl2Init(&stack->nst); - Isdnl3Init(&stack->nst); - } - - misdn_lib_get_l1_up(stack); - - if (stack->ptp) { - misdn_lib_get_l2_up(stack); - stack->l2link=0; - } - - - return stack; -} - - -struct misdn_stack* stack_te_init( int midev, int port, int ptp ) +struct misdn_stack* stack_init( int midev, int port, int ptp ) { int ret; unsigned char buff[1025]; @@ -983,18 +1123,16 @@ struct misdn_stack* stack_te_init( int midev, int port, int ptp ) stack_info_t *stinf; int i; layer_info_t li; - interface_info_t ii; + struct misdn_stack *stack = malloc(sizeof(struct misdn_stack)); if (!stack ) return NULL; - - //cb_log(2, "Init. Stack on port:%d\n",port); - cb_log(4, port, "Init. Stack on port:%d\n",port); + cb_log(8, port, "Init. Stack.\n"); memset(stack,0,sizeof(struct misdn_stack)); for (i=0; i<MAX_BCHANS + 1; i++ ) stack->channels[i]=0; - + stack->port=port; stack->midev=midev; stack->ptp=ptp; @@ -1003,11 +1141,12 @@ struct misdn_stack* stack_te_init( int midev, int port, int ptp ) stack->pri=0; msg_queue_init(&stack->downqueue); + msg_queue_init(&stack->upqueue); /* query port's requirements */ ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff)); if (ret < 0) { - cb_log(0, port, "%s: Cannot get stack info for port:%d (ret=%d)\n", __FUNCTION__, port, ret); + cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret); return(NULL); } @@ -1021,13 +1160,12 @@ struct misdn_stack* stack_te_init( int midev, int port, int ptp ) switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK) { case ISDN_PID_L0_TE_S0: - //cb_log(2, "TE Stack\n"); - stack->mode = TE_MODE; + stack->nt=0; break; case ISDN_PID_L0_NT_S0: - cb_log(4, port, "NT Stack\n"); + cb_log(8, port, "NT Stack\n"); - return stack_nt_init(stack,midev,port); + stack->nt=1; break; case ISDN_PID_L0_TE_U: @@ -1039,82 +1177,138 @@ struct misdn_stack* stack_te_init( int midev, int port, int ptp ) case ISDN_PID_L0_NT_UP2: break; case ISDN_PID_L0_TE_E1: - cb_log(4, port, "TE S2M Stack\n"); - stack->mode = TE_MODE; + cb_log(8, port, "TE S2M Stack\n"); + stack->nt=0; stack->pri=1; break; case ISDN_PID_L0_NT_E1: - cb_log(4, port, "TE S2M Stack\n"); - stack->mode = NT_MODE; + cb_log(8, port, "TE S2M Stack\n"); + stack->nt=1; stack->pri=1; - - return stack_nt_init(stack,midev,port); + break; default: - cb_log(0, port, "unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]); + cb_log(0, port, "this is a unknown port type 0x%08x\n", stinf->pid.protocol[0]); } - - if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP ) { /* || (nt&&ptp) || pri */ - stack->ptp = 1; - } else { - stack->ptp = 0; - } - stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, 3); - if (stack->lower_id <= 0) { - cb_log(0, stack->port, "No lower Id port:%d\n", stack->port); - return(NULL); + if (!stack->nt) { + if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP ) { + stack->ptp = 1; + } else { + stack->ptp = 0; + } } - - memset(&li, 0, sizeof(li)); + { - int l = sizeof(li.name); - strncpy(li.name, "user L4", l); - li.name[l-1] = 0; - } - li.object_id = -1; - li.extentions = 0; - - li.pid.protocol[4] = ISDN_PID_L4_CAPI20; - - li.pid.layermask = ISDN_LAYER((4)); - li.st = stack->d_stid; - stack->upper_id = mISDN_new_layer(midev, &li); - - if (stack->upper_id <= 0) { - cb_log(0, stack->port, "No Upper ID port:%d\n",stack->port); - return(NULL); - } - - memset(&ii, 0, sizeof(ii)); - ii.extentions = EXT_IF_EXCLUSIV | EXT_IF_CREATE; - ii.owner = stack->upper_id; - ii.peer = stack->lower_id; - ii.stat = IF_DOWN; - ret = mISDN_connect(midev, &ii); - if (ret) { - cb_log(0, stack->port, "No Connect port:%d\n", stack->port); - return NULL; + int ret; + int nt=stack->nt; + + cb_log(8, port, "Init. Stack.\n"); + + memset(&li, 0, sizeof(li)); + { + int l = sizeof(li.name); + strncpy(li.name,nt?"net l2":"user l4", l); + li.name[l-1] = 0; + } + li.object_id = -1; + li.extentions = 0; + li.pid.protocol[nt?2:4] = nt?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20; + li.pid.layermask = ISDN_LAYER((nt?2:4)); + li.st = stack->d_stid; + + + ret = mISDN_new_layer(midev, &li); + if (ret) { + cb_log(0, port, "%s: Cannot add layer %d to this port.\n", __FUNCTION__, nt?2:4); + return(NULL); + } + + + stack->upper_id = li.id; + ret = mISDN_register_layer(midev, stack->d_stid, stack->upper_id); + if (ret) + { + cb_log(0,port,"Cannot register layer %d of this port.\n", nt?2:4); + return(NULL); + } + + stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, nt?1:3); + if (stack->lower_id < 0) { + cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, nt?1:3); + return(NULL); + } + + stack->upper_id = mISDN_get_layerid(midev, stack->d_stid, nt?2:4); + if (stack->upper_id < 0) { + cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, 2); + return(NULL); + } + + cb_log(8, port, "NT Stacks upper_id %x\n",stack->upper_id); + + + /* create nst (nt-mode only) */ + if (nt) { + + memset(&stack->nst, 0, sizeof(net_stack_t)); + memset(&stack->mgr, 0, sizeof(manager_t)); + + stack->mgr.nst = &stack->nst; + stack->nst.manager = &stack->mgr; + + stack->nst.l3_manager = handle_event_nt; + stack->nst.device = midev; + stack->nst.cardnr = port; + stack->nst.d_stid = stack->d_stid; + + stack->nst.feature = FEATURE_NET_HOLD; + if (stack->ptp) + stack->nst.feature |= FEATURE_NET_PTP; + if (stack->pri) + stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID; + + stack->nst.l1_id = stack->lower_id; + stack->nst.l2_id = stack->upper_id; + + msg_queue_init(&stack->nst.down_queue); + + Isdnl2Init(&stack->nst); + Isdnl3Init(&stack->nst); + } + + stack->l1link=0; + stack->l2link=0; +#if 0 + if (!stack->nt) { + misdn_lib_get_short_status(stack); + } else { + misdn_lib_get_l1_up(stack); + if (!stack->ptp) misdn_lib_get_l1_up(stack); + misdn_lib_get_l2_up(stack); + } +#endif + misdn_lib_get_short_status(stack); + misdn_lib_get_l1_up(stack); + misdn_lib_get_l2_up(stack); } - - misdn_lib_get_l1_up(stack); - misdn_lib_get_l2_status(stack); + + cb_log(8,0,"stack_init: port:%d lowerId:%x upperId:%x\n",stack->port,stack->lower_id, stack->upper_id); - /* initially, we assume that the link is NOT up */ - stack->l2link = 0; - stack->l1link = 0; - - stack->next=NULL; - return stack; - } -void stack_te_destroy(struct misdn_stack* stack) + +void stack_destroy(struct misdn_stack* stack) { char buf[1024]; if (!stack) return; + + if (stack->nt) { + cleanup_Isdnl2(&stack->nst); + cleanup_Isdnl3(&stack->nst); + } if (stack->lower_id) mISDN_write_frame(stack->midev, buf, stack->lower_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); @@ -1127,11 +1321,12 @@ void stack_te_destroy(struct misdn_stack* stack) struct misdn_stack * find_stack_by_addr(int addr) { struct misdn_stack *stack; - + for (stack=glob_mgr->stack_list; stack; stack=stack->next) { - if ( stack->upper_id == addr) return stack; + if ( (stack->upper_id&STACK_ID_MASK) == (addr&STACK_ID_MASK)) return stack; + } return NULL; @@ -1193,72 +1388,113 @@ struct misdn_bchannel *find_bc_holded(struct misdn_stack *stack) struct misdn_bchannel *find_bc_by_addr(unsigned long addr) { - int port = addr & IF_CONTRMASK; struct misdn_stack* stack; int i; - + for (stack=glob_mgr->stack_list; stack; stack=stack->next) { - - if (stack->port == port) { - for (i=0; i< stack->b_num; i++) { - if (stack->bc[i].addr==addr) { - return &stack->bc[i]; - } + + for (i=0; i< stack->b_num; i++) { + + if ( (stack->bc[i].addr&STACK_ID_MASK)==(addr&STACK_ID_MASK) || stack->bc[i].layer_id== addr ) { + return &stack->bc[i]; } } + } - + + + return NULL; +} + + +struct misdn_bchannel *find_bc_by_channel(int port, int channel) +{ + struct misdn_stack* stack=find_stack_by_port(port); + int i; + + if (!stack) return NULL; + + for (i=0; i< stack->b_num; i++) { + if ( stack->bc[i].channel== channel ) { + return &stack->bc[i]; + } + } + return NULL; } + int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm) { struct misdn_stack *stack=get_stack_by_bc(bc); - if (stack->mode == TE_MODE) { + + if (!stack->nt) { + switch (event) { case EVENT_CONNECT_ACKNOWLEDGE: - manager_bchannel_activate(bc); +#if 0 + if ( !misdn_cap_is_speech(bc->capability)) { + int ret=setup_bc(bc); + if (ret == -EINVAL){ + cb_log(0,bc->port,"send_event: setup_bc failed\n"); + } + } +#endif break; case EVENT_CONNECT: - + if ( *bc->crypt_key ) { - cb_log(4, stack->port, "ENABLING BLOWFISH port:%d channel:%d oad%d:%s dad%d:%s\n", stack->port, bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad); - + cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad); manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) ); } - case EVENT_SETUP: - if (bc->channel>0 && bc->channel<255) - set_chan_in_stack(stack, bc->channel); - break; case EVENT_ALERTING: case EVENT_PROGRESS: case EVENT_PROCEEDING: case EVENT_SETUP_ACKNOWLEDGE: + + setup_bc(bc); + + case EVENT_SETUP: { - struct misdn_stack *stack=find_stack_by_port(frm->addr&IF_CONTRMASK); - if (!stack) return -1; - if (bc->channel == 0xff) { bc->channel=find_free_chan_in_stack(stack, 0); if (!bc->channel) { cb_log(0, stack->port, "Any Channel Requested, but we have no more!!\n"); break; } - } - - if (stack->mode == TE_MODE) { - setup_bc(bc); + } + + if (bc->channel >0 && bc->channel<255) { + set_chan_in_stack(stack ,bc->channel); + } + +#if 0 + int ret=setup_bc(bc); + if (ret == -EINVAL){ + cb_log(0,bc->port,"handle_event: setup_bc failed\n"); + misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); } +#endif } - + break; + + case EVENT_RELEASE_COMPLETE: + case EVENT_RELEASE: + if (bc->channel>0) + empty_chan_in_stack(stack,bc->channel); + int tmpcause=bc->cause; + empty_bc(bc); + bc->cause=tmpcause; + clean_up_bc(bc); + break; default: break; } @@ -1271,31 +1507,28 @@ int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm) int handle_new_process(struct misdn_stack *stack, iframe_t *frm) { - struct misdn_bchannel* bc=misdn_lib_get_free_bc(frm->addr&IF_CONTRMASK, 0); + struct misdn_bchannel* bc=misdn_lib_get_free_bc(stack->port, 0); + if (!bc) { - cb_log(0, 0, " --> !! lib: No free channel!\n"); + cb_log(0, stack->port, " --> !! lib: No free channel!\n"); return -1; } - cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo); + cb_log(7, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo); bc->l3_id=frm->dinfo; - - if (mypid>5000) mypid=0; - bc->pid=mypid++; return 0; } -int handle_cr ( iframe_t *frm) +int handle_cr ( struct misdn_stack *stack, iframe_t *frm) { - struct misdn_stack *stack=find_stack_by_port(frm->addr&IF_CONTRMASK); - if (!stack) return -1; switch (frm->prim) { case CC_NEW_CR|INDICATION: - cb_log(4, stack->port, " --> lib: NEW_CR Ind with l3id:%x port:%d\n",frm->dinfo, stack->port); - handle_new_process(stack, frm); + cb_log(7, stack->port, " --> lib: NEW_CR Ind with l3id:%x on this port.\n",frm->dinfo); + if (handle_new_process(stack, frm) <0) + return -1; return 1; case CC_NEW_CR|CONFIRM: return 1; @@ -1312,22 +1545,29 @@ int handle_cr ( iframe_t *frm) struct misdn_bchannel dummybc; if (!bc) { - cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on port:%d\n", frm->dinfo, stack->port); + cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on this port.\n", frm->dinfo); memset (&dummybc,0,sizeof(dummybc)); dummybc.port=stack->port; dummybc.l3_id=frm->dinfo; + dummybc.nt=stack->nt; bc=&dummybc; } if (bc) { cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo); - empty_chan_in_stack(stack,bc->channel); + if (bc->channel>0) + empty_chan_in_stack(stack,bc->channel); empty_bc(bc); + clean_up_bc(bc); + dump_chan_list(stack); - bc->pid = 0; - cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data); + /*bc->pid = 0;*/ + bc->need_disconnect=0; + bc->need_release=0; + bc->need_release_complete=0; + cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data); if (bc->stack_holder) { cb_log(4,stack->port, "REMOVEING Holder\n"); stack_holder_remove( stack, bc); @@ -1335,7 +1575,7 @@ int handle_cr ( iframe_t *frm) } } else { - if (stack->mode == NT_MODE) + if (stack->nt) cb_log(4, stack->port, "BC with dinfo: %x not found.. (prim was %x and addr %x)\n",frm->dinfo, frm->prim, frm->addr); } @@ -1358,10 +1598,10 @@ void misdn_lib_release(struct misdn_bchannel *bc) return; } - if (bc->channel>=0) { + if (bc->channel>0) { empty_chan_in_stack(stack,bc->channel); - empty_bc(bc); } + empty_bc(bc); clean_up_bc(bc); } @@ -1369,7 +1609,7 @@ void misdn_lib_release(struct misdn_bchannel *bc) int misdn_lib_get_port_up (int port) -{ /* Pull Up L1 if we have JOLLY */ +{ /* Pull Up L1 */ struct misdn_stack *stack; for (stack=glob_mgr->stack_list; @@ -1390,37 +1630,75 @@ int misdn_lib_get_port_up (int port) } +int misdn_lib_get_port_down (int port) +{ /* Pull Down L1 */ + struct misdn_stack *stack; + for (stack=glob_mgr->stack_list; + stack; + stack=stack->next) { + if (stack->port == port) { + if (stack->l2link) + misdn_lib_get_l2_down(stack); + misdn_lib_get_l1_down(stack); + return 0; + } + } + return 0; +} + int misdn_lib_send_facility(struct misdn_bchannel *bc, enum facility_type fac, void *data) { - bc->facility=fac; - strcpy(bc->facility_calldeflect_nr,(char*)data); + switch (fac) { + case FACILITY_CALLDEFLECT: + strcpy(bc->out_fac.calldeflect_nr,(char*)data); + break; + default: + cb_log(1,bc?bc->port:0,"We don't handle this facility yet: %d\n",fac); + return 0; + } + + bc->out_fac_type=fac; misdn_lib_send_event(bc,EVENT_FACILITY); return 0; } -int misdn_lib_port_up(int port) +int misdn_lib_port_up(int port, int check) { struct misdn_stack *stack; - + + for (stack=glob_mgr->stack_list; stack; stack=stack->next) { + if ( !stack->ptp && !check) return 1; + if (stack->port == port) { - if (stack->mode == NT_MODE) { - if (stack->l1link) + + if (stack->blocked) { + cb_log(0,port, "Port Blocked:%d L2:%d L1:%d\n", stack->blocked, stack->l2link, stack->l1link); + return -1; + } + + if (stack->ptp ) { + + if (stack->l1link && stack->l2link) { return 1; - else + } else { + cb_log(0,port, "Port Down L2:%d L1:%d\n", + stack->l2link, stack->l1link); return 0; + } } else { - if (stack->l1link) + if ( stack->l1link) return 1; - else + else { + cb_log(0,port, "Port down PMP\n"); return 0; + } } - } } @@ -1433,38 +1711,31 @@ handle_event_nt(void *dat, void *arg) { manager_t *mgr = (manager_t *)dat; msg_t *msg = (msg_t *)arg; -#ifdef MISDNUSER_JOLLY mISDNuser_head_t *hh; -#else - mISDN_head_t *hh; -#endif + int reject=0; + struct misdn_stack *stack=find_stack_by_mgr(mgr); int port; if (!msg || !mgr) return(-EINVAL); -#ifdef MISDNUSER_JOLLY hh=(mISDNuser_head_t*)msg->data; -#else - hh=(mISDN_head_t*)msg->data; -#endif - - port=hh->dinfo & IF_CONTRMASK; - - cb_log(4, stack->port, " --> lib: prim %x dinfo %x port: %d\n",hh->prim, hh->dinfo ,stack->port); - + port=stack->port; + + cb_log(5, stack->port, " --> lib: prim %x dinfo %x\n",hh->prim, hh->dinfo); { switch(hh->prim){ - case CC_RETRIEVE|INDICATION: { iframe_t frm; /* fake te frm to add callref to global callreflist */ frm.dinfo = hh->dinfo; - frm.addr=stack->upper_id; + + frm.addr=stack->upper_id | FLG_MSG_DOWN; + frm.prim = CC_NEW_CR|INDICATION; - if (handle_cr(&frm)< 0) { + if (handle_cr( stack, &frm)< 0) { msg_t *dmsg; cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo); dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1); @@ -1474,11 +1745,16 @@ handle_event_nt(void *dat, void *arg) } struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); - cb_event(EVENT_NEW_BC, bc, glob_mgr->user_data); struct misdn_bchannel *hold_bc=stack_holder_find(stack,bc->l3_id); + if (hold_bc) { + cb_log(4, stack->port, "REMOVEING Holder\n"); stack_holder_remove(stack, hold_bc); + + memcpy(bc,hold_bc,sizeof(struct misdn_bchannel)); + cb_event(EVENT_NEW_BC, hold_bc, bc); + free(hold_bc); } @@ -1486,16 +1762,14 @@ handle_event_nt(void *dat, void *arg) break; - case CC_SETUP|CONFIRM: { struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE)); - - cb_log(4, bc?stack->port:0, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID is %x\n",l3id ); - - if (!bc) { cb_log(4, 0, "Bc Not found (after SETUP CONFIRM)\n"); return 0; } + cb_log(4, stack->port, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID is %x\n",l3id ); + if (!bc) { cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n"); return 0; } + cb_log (2,bc->port,"I IND :CC_SETUP|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id); bc->l3_id=l3id; cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data); } @@ -1509,7 +1783,7 @@ handle_event_nt(void *dat, void *arg) frm.addr=stack->upper_id; frm.prim = CC_NEW_CR|INDICATION; - if (handle_cr(&frm)< 0) { + if (handle_cr(stack, &frm)< 0) { msg_t *dmsg; cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo); dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1); @@ -1520,17 +1794,35 @@ handle_event_nt(void *dat, void *arg) } break; - - case CC_CONNECT|INDICATION: + case CC_CONNECT_ACKNOWLEDGE|INDICATION: +#if 0 + { + struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); + if (bc) { + if ( !misdn_cap_is_speech(bc->capability)) { + int ret=setup_bc(bc); + if (ret == -EINVAL){ + cb_log(0,bc->port,"send_event: setup_bc failed\n"); + + } + } + } + } +#endif + break; + case CC_ALERTING|INDICATION: case CC_PROCEEDING|INDICATION: - + case CC_SETUP_ACKNOWLEDGE|INDICATION: + if(!stack->ptp) break; + case CC_CONNECT|INDICATION: { +#if 0 struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); if (!bc) { msg_t *dmsg; - cb_log(0, stack->port,"!!!! We didn't found our bc, dinfo:%x port:%d\n",hh->dinfo, stack->port); + cb_log(0, stack->port,"!!!! We didn't found our bc, dinfo:%x on this port.\n",hh->dinfo); cb_log(0, stack->port, "Releaseing call %x (No free Chan for you..)\n", hh->dinfo); dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1); @@ -1539,8 +1831,12 @@ handle_event_nt(void *dat, void *arg) return 0; } - - setup_bc(bc); + int ret=setup_bc(bc); + if (ret == -EINVAL){ + cb_log(0,bc->port,"handle_event_nt: setup_bc failed\n"); + misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); + } +#endif } break; case CC_DISCONNECT|INDICATION: @@ -1548,15 +1844,30 @@ handle_event_nt(void *dat, void *arg) struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); if (!bc) { bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000); - if (bc) { //repair reject bug + if (bc) { /*repair reject bug*/ int myprocid=bc->l3_id&0x0000ffff; hh->dinfo=(hh->dinfo&0xffff0000)|myprocid; - cb_log(4,stack->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo); + cb_log(3,stack->port,"Reject dinfo: %x cause:%d\n",hh->dinfo,bc->cause); + reject=1; } } } break; - + + case CC_FACILITY|INDICATION: + { + struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); + if (!bc) { + bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000); + if (bc) { + int myprocid=bc->l3_id&0x0000ffff; + hh->dinfo=(hh->dinfo&0xffff0000)|myprocid; + cb_log(4,bc->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo); + } + } + } + break; + case CC_RELEASE_COMPLETE|INDICATION: break; @@ -1574,13 +1885,8 @@ handle_event_nt(void *dat, void *arg) break; case CC_RELEASE|CONFIRM: - { - struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); - cb_log(4, stack->port, " --> RELEASE CONFIRM, sending RELEASE_COMPLETE\n"); - if (bc) misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); - } - hh->prim=CC_RELEASE|INDICATION; - break; + break; + case CC_RELEASE|INDICATION: break; @@ -1590,42 +1896,35 @@ handle_event_nt(void *dat, void *arg) struct misdn_bchannel dummybc; iframe_t frm; /* fake te frm to remove callref from global callreflist */ frm.dinfo = hh->dinfo; - frm.addr=stack->upper_id; + + frm.addr=stack->upper_id | FLG_MSG_DOWN; + frm.prim = CC_RELEASE_CR|INDICATION; cb_log(4, stack->port, " --> Faking Realease_cr for %x\n",frm.addr); /** removing procid **/ - if (!bc) { - cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on port:%d\n", hh->dinfo, stack->port); + cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on this port.\n", hh->dinfo); memset (&dummybc,0,sizeof(dummybc)); dummybc.port=stack->port; dummybc.l3_id=hh->dinfo; + dummybc.nt=stack->nt; bc=&dummybc; } if (bc) { -#ifdef MISDNUSER_JOLLY if ( (bc->l3_id & 0xff00) == 0xff00) { - cb_log(4, stack->port, " --> Removing Process Id:%x on port:%d\n", bc->l3_id&0xff, stack->port); + cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", bc->l3_id&0xff); stack->procids[bc->l3_id&0xff] = 0 ; } -#else - if ( (bc->l3_id & 0xfff0) == 0xfff0) { - cb_log(4, stack->port, " --> Removing Process Id:%x on port:%d\n", bc->l3_id&0xf, stack->port); - stack->procids[bc->l3_id&0xf] = 0 ; - - } - -#endif - } - else cb_log(0, stack->port, "Couldnt find BC so I couldnt remove the Process!!!! this is bad Port:%d\n", stack->port ); + else cb_log(0, stack->port, "Couldnt find BC so I couldnt remove the Process!!!! this is a bad port.\n"); - handle_cr(&frm); + if (handle_cr(stack, &frm)<0) { + } + free_msg(msg); return 0 ; } - break; case CC_NEW_CR|INDICATION: @@ -1634,25 +1933,16 @@ handle_event_nt(void *dat, void *arg) { struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE)); - if (!bc) { cb_log(0, 0, " --> In NEW_CR: didn't found bc ??\n"); return -1;}; -#ifdef MISDNUSER_JOLLY + if (!bc) { cb_log(0, stack->port, " --> In NEW_CR: didn't found bc ??\n"); return -1;}; if (((l3id&0xff00)!=0xff00) && ((bc->l3_id&0xff00)==0xff00)) { - cb_log(4, stack->port, " --> Removing Process Id:%x on port:%d\n", 0xff&bc->l3_id, stack->port); + cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", 0xff&bc->l3_id); stack->procids[bc->l3_id&0xff] = 0 ; } -#else - if (((l3id&0xfff0)!=0xfff0) && ((bc->l3_id&0xfff0)==0xfff0)) { - cb_log(4, stack->port, "Removing Process Id:%x on port:%d\n", 0xf&bc->l3_id, stack->port); - stack->procids[bc->l3_id&0xf] = 0 ; - } - -#endif cb_log(4, stack->port, "lib: Event_ind:CC_NEW_CR : very new L3ID is %x\n",l3id ); bc->l3_id =l3id; cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data); - free_msg(msg); return 0; } @@ -1660,24 +1950,44 @@ handle_event_nt(void *dat, void *arg) case DL_ESTABLISH | INDICATION: case DL_ESTABLISH | CONFIRM: { - cb_log(4, stack->port, "%% GOT L2 Activate Info port:%d\n",stack->port); + cb_log(3, stack->port, "%% GOT L2 Activate Info.\n"); + + if (stack->ptp && stack->l2link) { + cb_log(0, stack->port, "%% GOT L2 Activate Info. but we're activated already.. this l2 is faulty, blocking port\n"); + cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data); + } + stack->l2link = 1; - + stack->l2upcnt=0; + free_msg(msg); return 0; } break; + case DL_RELEASE | INDICATION: case DL_RELEASE | CONFIRM: { - cb_log(4, stack->port, "%% GOT L2 DeActivate Info port:%d\n",stack->port); - stack->l2link = 0; - - /** Clean the L3 here **/ - if (cb_clearl3_true()) - clear_l3(stack); + if (stack->ptp) { + cb_log(3 , stack->port, "%% GOT L2 DeActivate Info.\n"); + + if (stack->l2upcnt>3) { + cb_log(0 , stack->port, "!!! Could not Get the L2 up after 3 Attemps!!!\n"); + } else { +#if 0 + if (stack->nt) misdn_lib_reinit_nt_stack(stack->port); +#endif + if (stack->l1link) { + misdn_lib_get_l2_up(stack); + stack->l2upcnt++; + } + } + + } else + cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n"); + stack->l2link = 0; free_msg(msg); return 0; } @@ -1685,8 +1995,6 @@ handle_event_nt(void *dat, void *arg) } } - - { /* Parse Events and fire_up to App. */ struct misdn_bchannel *bc; @@ -1698,21 +2006,75 @@ handle_event_nt(void *dat, void *arg) if (!bc) { - cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on port:%d\n", hh->dinfo, stack->port); + cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x).\n", hh->dinfo); memset (&dummybc,0,sizeof(dummybc)); dummybc.port=stack->port; dummybc.l3_id=hh->dinfo; + dummybc.nt=stack->nt; bc=&dummybc; } if (bc ) { isdn_msg_parse_event(msgs_g,msg,bc, 1); + + switch (event) { + case EVENT_SETUP: + if (bc->channel>0 && bc->channel<255) { + + if (stack->ptp) + set_chan_in_stack(stack, bc->channel); + else + cb_log(0,stack->port," --> PTMP but channel requested\n"); + + } else { + + bc->channel = find_free_chan_in_stack(stack, 0); + if (!bc->channel) { + cb_log(0, stack->port, " No free channel at the moment\n"); + + msg_t *dmsg; + + cb_log(0, stack->port, "Releaseing call %x (No free Chan for you..)\n", hh->dinfo); + dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1); + stack->nst.manager_l3(&stack->nst, dmsg); + free_msg(msg); + return 0; + } + + } +#if 0 + setup_bc(bc); +#endif + + break; + case EVENT_RELEASE: + case EVENT_RELEASE_COMPLETE: + if (bc->channel>0) + empty_chan_in_stack(stack, bc->channel); + int tmpcause=bc->cause; + empty_bc(bc); + bc->cause=tmpcause; + clean_up_bc(bc); + break; + + default: + break; + } if(!isdn_get_info(msgs_g,event,1)) { cb_log(4, stack->port, "Unknown Event Ind: prim %x dinfo %x\n",hh->prim, hh->dinfo); } else { + if (reject) { + switch(bc->cause){ + case 17: + cb_log(1, stack->port, "Siemens Busy reject..\n"); + + break; + default: + break; + } + } cb_event(event, bc, glob_mgr->user_data); } - } else { cb_log(4, stack->port, "No BC found with l3id: prim %x dinfo %x\n",hh->prim, hh->dinfo); @@ -1749,7 +2111,7 @@ int handle_timers(msg_t* msg) stack = stack->next) { itimer_t *it; - if (stack->mode != NT_MODE) continue; + if (!stack->nt) continue; it = stack->nst.tlist; /* find timer */ @@ -1780,129 +2142,221 @@ int handle_timers(msg_t* msg) +void misdn_lib_tone_generator_start(struct misdn_bchannel *bc) +{ + bc->generate_tone=1; +} + +void misdn_lib_tone_generator_stop(struct misdn_bchannel *bc) +{ + bc->generate_tone=0; +} + static int do_tone(struct misdn_bchannel *bc, int len) { - char buf[4096 + mISDN_HEADER_LEN]; - iframe_t *frm= (iframe_t*)buf; - int r; - struct misdn_stack *stack=get_stack_by_bc(bc); + bc->tone_cnt=len; + + if (bc->generate_tone) { + cb_event(EVENT_TONE_GENERATE, bc, glob_mgr->user_data); + + if ( !bc->nojitter ) { + misdn_tx_jitter(bc,len); + } + + return 1; + } - if (bc->tone == TONE_NONE) return 0; + return 0; +} - frm->prim = DL_DATA|REQUEST; - frm->dinfo = 0; - frm->addr = bc->addr | IF_DOWN; - - bc->tone_cnt+=len; - if (bc->tone_cnt < TONE_425_SIZE) return 1; - switch(bc->tone) { - case TONE_DIAL: - { - frm->len = TONE_425_SIZE; - memcpy(&buf[mISDN_HEADER_LEN], tone_425_flip,TONE_425_SIZE); - - r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC); - if (r<frm->len) { - perror("Error written less than told bytes :(\n"); +void misdn_tx_jitter(struct misdn_bchannel *bc, int len) +{ + char buf[4096 + mISDN_HEADER_LEN]; + char *data=&buf[mISDN_HEADER_LEN]; + iframe_t *txfrm= (iframe_t*)buf; + int jlen, r; + + jlen=cb_jb_empty(bc,data,len); + + if (jlen) { + flip_buf_bits( data, jlen); + + if (jlen < len) { + cb_log(7,bc->port,"Jitterbuffer Underrun.\n"); } - } - break; - case TONE_ALERTING: - bc->tone_cnt2++; - - if (bc->tone_cnt2 <= TONE_ALERT_CNT) { - frm->len = TONE_425_SIZE; - memcpy(&buf[mISDN_HEADER_LEN], tone_425_flip,TONE_425_SIZE); - r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC); - if (r<frm->len) { - perror("Error written less than told bytes :(\n"); - } - } else if (bc->tone_cnt2 <= (TONE_ALERT_SILENCE_CNT)) { - frm->len = TONE_SILENCE_SIZE; - memcpy(&buf[mISDN_HEADER_LEN], tone_silence_flip ,TONE_SILENCE_SIZE); - r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC); - } else { - bc->tone_cnt2=-1; + txfrm->prim = DL_DATA|REQUEST; + + txfrm->dinfo = 0; + + txfrm->addr = bc->addr|FLG_MSG_DOWN; /* | IF_DOWN; */ + + txfrm->len =jlen; + cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len); + + r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 ); + } else { +#define MISDN_GEN_SILENCE +#ifdef MISDN_GEN_SILENCE + int cnt=len/TONE_SILENCE_SIZE; + int rest=len%TONE_SILENCE_SIZE; + int i; + + for (i=0; i<cnt; i++) { + memcpy(data, tone_silence_flip, TONE_SILENCE_SIZE ); + data +=TONE_SILENCE_SIZE; } - break; - case TONE_BUSY: - bc->tone_cnt2++; - - if (bc->tone_cnt2 <= TONE_BUSY_CNT) { - frm->len = TONE_425_SIZE; - memcpy(&buf[mISDN_HEADER_LEN], tone_425_flip,TONE_425_SIZE); - r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC); - if (r<frm->len) { - perror("Error written less than told bytes :(\n"); - } - } else if (bc->tone_cnt2 <= (TONE_BUSY_SILENCE_CNT)) { - frm->len = TONE_SILENCE_SIZE; - memcpy(&buf[mISDN_HEADER_LEN], tone_silence_flip ,TONE_SILENCE_SIZE); - r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_1SEC); - } else { - bc->tone_cnt2=-1; + + if (rest) { + memcpy(data, tone_silence_flip, rest); } - break; - case TONE_FILE: - break; - case TONE_NONE: - return 0; + + txfrm->prim = DL_DATA|REQUEST; + + txfrm->dinfo = 0; + + txfrm->addr = bc->addr|FLG_MSG_DOWN; /* | IF_DOWN; */ + + txfrm->len =len; + cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len); + + r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 ); +#endif } - - bc->tone_cnt -= TONE_425_SIZE ; - return 1; } - - int handle_bchan(msg_t *msg) { iframe_t *frm= (iframe_t*)msg->data; - struct misdn_bchannel *bc; + + + struct misdn_bchannel *bc=find_bc_by_addr(frm->addr); - bc=find_bc_by_addr(frm->addr); + if (!bc) { + cb_log(1,0,"handle_bchan: BC not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo); + return 0 ; + } - if (!bc) return 0 ; - struct misdn_stack *stack=get_stack_by_bc(bc); - - if (!stack) return 0; + + if (!stack) { + cb_log(0, bc->port,"handle_bchan: STACK not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo); + return 0; + } switch (frm->prim) { + + case MGR_SETSTACK| CONFIRM: + cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|CONFIRM pid:%d\n",bc->pid); + break; + + case MGR_SETSTACK| INDICATION: + cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|IND pid:%d\n",bc->pid); + break; +#if 0 + AGAIN: + bc->addr = mISDN_get_layerid(stack->midev, bc->b_stid, bc->layer); + if (!bc->addr) { + + if (errno == EAGAIN) { + usleep(1000); + goto AGAIN; + } + + cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno)); + + /* we kill the channel later, when we received some + data. */ + bc->addr= frm->addr; + } else if ( bc->addr < 0) { + cb_log(0, stack->port,"$$$ bc->addr <0 Error:%s\n",strerror(errno)); + bc->addr=0; + } + + cb_log(4, stack->port," --> Got Adr %x\n", bc->addr); + + free_msg(msg); + + + switch(bc->bc_state) { + case BCHAN_SETUP: + bc_state_change(bc,BCHAN_SETUPED); + break; + + case BCHAN_CLEAN_REQUEST: + default: + cb_log(0, stack->port," --> STATE WASN'T SETUP (but %s) in SETSTACK|IND pid:%d\n",bc_state2str(bc->bc_state), bc->pid); + clean_up_bc(bc); + } + return 1; +#endif + + case MGR_DELLAYER| INDICATION: + cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|IND pid:%d\n",bc->pid); + break; + + case MGR_DELLAYER| CONFIRM: + cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|CNF pid:%d\n",bc->pid); + + bc->pid=0; + bc->addr=0; + + free_msg(msg); + return 1; + case PH_ACTIVATE | INDICATION: case DL_ESTABLISH | INDICATION: - cb_log(4, stack->port, "BCHAN: ACT Ind\n"); + cb_log(3, stack->port, "BCHAN: ACT Ind pid:%d\n", bc->pid); + free_msg(msg); return 1; case PH_ACTIVATE | CONFIRM: case DL_ESTABLISH | CONFIRM: - cb_log(4, stack->port, "BCHAN: bchan ACT Confirm\n"); + + cb_log(3, stack->port, "BCHAN: bchan ACT Confirm pid:%d\n",bc->pid); free_msg(msg); - + return 1; + + case DL_ESTABLISH | REQUEST: + { + char buf[128]; + mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_ESTABLISH | CONFIRM, 0,0, NULL, TIMEOUT_1SEC); + } + free_msg(msg); + return 1; + + case DL_RELEASE|REQUEST: + { + char buf[128]; + mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_RELEASE| CONFIRM, 0,0, NULL, TIMEOUT_1SEC); + } + free_msg(msg); + return 1; case PH_DEACTIVATE | INDICATION: case DL_RELEASE | INDICATION: - cb_log (4, stack->port, "BCHAN: DeACT Ind\n"); + cb_log (3, stack->port, "BCHAN: DeACT Ind pid:%d\n",bc->pid); + free_msg(msg); return 1; case PH_DEACTIVATE | CONFIRM: case DL_RELEASE | CONFIRM: - cb_log(4, stack->port, "BCHAN: DeACT Conf\n"); + cb_log(3, stack->port, "BCHAN: DeACT Conf pid:%d\n",bc->pid); + free_msg(msg); return 1; case PH_CONTROL|INDICATION: { - unsigned long cont = *((unsigned long *)&frm->data.p); + unsigned int cont = *((unsigned int *)&frm->data.p); - cb_log(4, stack->port, "PH_CONTROL: port:%d channel:%d oad%d:%s dad%d:%s \n", stack->port, bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad); + cb_log(4, stack->port, "PH_CONTROL: channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad); if ((cont&~DTMF_TONE_MASK) == DTMF_TONE_VAL) { int dtmf = cont & DTMF_TONE_MASK; @@ -1925,7 +2379,16 @@ int handle_bchan(msg_t *msg) } } break; - + + case PH_DATA|REQUEST: + case DL_DATA|REQUEST: + cb_log(0, stack->port, "DL_DATA REQUEST \n"); + do_tone(bc, 64); + + free_msg(msg); + return 1; + + case PH_DATA|INDICATION: case DL_DATA|INDICATION: { @@ -1935,44 +2398,63 @@ int handle_bchan(msg_t *msg) /** Anyway flip the bufbits **/ if ( misdn_cap_is_speech(bc->capability) ) flip_buf_bits(bc->bframe, bc->bframe_len); - + + + if (!bc->bframe_len) { + cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr); + free_msg(msg); + return 1; + } + + if ( (bc->addr&STACK_ID_MASK) != (frm->addr&STACK_ID_MASK) ) { + cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr); + free_msg(msg); + return 1; + } #if MISDN_DEBUG cb_log(0, stack->port, "DL_DATA INDICATION Len %d\n", frm->len); + #endif - if (bc->active && frm->len > 0) { - if ( !do_tone(bc, frm->len) ) { + if ( (bc->bc_state == BCHAN_ACTIVATED) && frm->len > 0) { + int t; + +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"do_tone START\n"); +#endif + t=do_tone(bc,frm->len); + +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"do_tone STOP (%d)\n",t); +#endif + if ( !t ) { if ( misdn_cap_is_speech(bc->capability)) { if ( !bc->nojitter ) { - char buf[4096 + mISDN_HEADER_LEN]; - iframe_t *txfrm= (iframe_t*)buf; - int len, r; - - len = ibuf_usedcount(bc->misdnbuf); - - if (len < frm->len) { - /** send nothing - * till we are synced - **/ - } else { - - txfrm->prim = DL_DATA|REQUEST; - txfrm->dinfo = 0; - txfrm->addr = bc->addr; /* | IF_DOWN; */ - txfrm->len = frm->len; - ibuf_memcpy_r(&buf[mISDN_HEADER_LEN], bc->misdnbuf,frm->len); - cb_log(9, stack->port, "Transmitting %d samples 2 misdn\n", txfrm->len); - - r=mISDN_write(stack->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 ); - - } - +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"tx_jitter START\n"); +#endif + misdn_tx_jitter(bc,frm->len); +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"tx_jitter STOP\n"); +#endif } } + +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"EVENT_B_DATA START\n"); +#endif + + int i=cb_event( EVENT_BCHAN_DATA, bc, glob_mgr->user_data); +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"EVENT_B_DATA STOP\n"); +#endif - cb_event( EVENT_BCHAN_DATA, bc, glob_mgr->user_data); + if (i<0) { + cb_log(10,stack->port,"cb_event returned <0\n"); + /*clean_up_bc(bc);*/ + } } } free_msg(msg); @@ -1980,22 +2462,27 @@ int handle_bchan(msg_t *msg) } + case PH_CONTROL | CONFIRM: + cb_log(4, stack->port, "PH_CONTROL|CNF bc->addr:%x\n", frm->addr); + free_msg(msg); + return 1; + case PH_DATA | CONFIRM: case DL_DATA|CONFIRM: #if MISDN_DEBUG + cb_log(0, stack->port, "Data confirmed\n"); + #endif free_msg(msg); + return 1; - break; case DL_DATA|RESPONSE: #if MISDN_DEBUG cb_log(0, stack->port, "Data response\n"); + #endif break; - - case DL_DATA | REQUEST: - break; } return 0; @@ -2008,30 +2495,32 @@ int handle_frm_nt(msg_t *msg) iframe_t *frm= (iframe_t*)msg->data; struct misdn_stack *stack; int err=0; + + stack=find_stack_by_addr( frm->addr ); + + - stack=find_stack_by_addr((frm->addr & IF_ADDRMASK ) ); - - if (!stack || stack->mode != NT_MODE) { + if (!stack || !stack->nt) { return 0; } - + if ((err=stack->nst.l1_l2(&stack->nst,msg))) { if (nt_err_cnt > 0 ) { if (nt_err_cnt < 100) { nt_err_cnt++; - cb_log(0, stack->port, "NT Stack sends us error: %d port:%d\n", err,stack->port); + cb_log(0, stack->port, "NT Stack sends us error: %d \n", err); } else if (nt_err_cnt < 105){ - cb_log(0, stack->port, "NT Stack sends us error: %d port:%d over 100 times, so I'll stop this message\n", err,stack->port); + cb_log(0, stack->port, "NT Stack sends us error: %d over 100 times, so I'll stop this message\n", err); nt_err_cnt = - 1; } } free_msg(msg); return 1; - + } - + return 1; } @@ -2039,16 +2528,24 @@ int handle_frm_nt(msg_t *msg) int handle_frm(msg_t *msg) { iframe_t *frm = (iframe_t*) msg->data; - struct misdn_stack *stack=find_stack_by_addr(frm->addr & IF_ADDRMASK); - - if (!stack || stack->mode != TE_MODE) { + + struct misdn_stack *stack=find_stack_by_addr(frm->addr); + + if (!stack || stack->nt) { return 0; } + + cb_log(4,stack?stack->port:0,"handle_frm: frm->addr:%x frm->prim:%x\n",frm->addr,frm->prim); { struct misdn_bchannel *bc; + int ret=handle_cr(stack, frm); + + if (ret<0) { + cb_log(3,stack?stack->port:0,"handle_frm: handle_cr <0 prim:%x addr:%x\n", frm->prim, frm->addr); + } - if(handle_cr(frm)) { + if(ret) { free_msg(msg); return 1; } @@ -2060,7 +2557,7 @@ int handle_frm(msg_t *msg) enum event_response_e response=RESPONSE_OK; isdn_msg_parse_event(msgs_g,msg,bc, 0); - + /** Preprocess some Events **/ handle_event(bc, event, frm); /* shoot up event to App: */ @@ -2074,35 +2571,47 @@ int handle_frm(msg_t *msg) if (event == EVENT_SETUP) { switch (response) { case RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE: - cb_log(0, stack->port, "TOTALY IGNORING SETUP: port:%d\n", frm->addr&IF_CONTRMASK); + + cb_log(0, stack->port, "TOTALY IGNORING SETUP \n"); + break; case RESPONSE_IGNORE_SETUP: /* I think we should send CC_RELEASE_CR, but am not sure*/ - empty_chan_in_stack(stack, bc->channel); + + bc->out_cause=16; + misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); + if (bc->channel>0) + empty_chan_in_stack(stack, bc->channel); empty_bc(bc); - - cb_log(0, stack->port, "GOT IGNORE SETUP: port:%d\n", frm->addr&IF_CONTRMASK); + bc_state_change(bc,BCHAN_CLEANED); + + cb_log(0, stack->port, "GOT IGNORE SETUP\n"); + + break; case RESPONSE_OK: - cb_log(4, stack->port, "GOT SETUP OK: port:%d\n", frm->addr&IF_CONTRMASK); + cb_log(4, stack->port, "GOT SETUP OK\n"); + + break; default: break; } } - - cb_log(5, stack->port, "Freeing Msg on prim:%x port:%d\n",frm->prim, frm->addr&IF_CONTRMASK); + + cb_log(5, stack->port, "Freeing Msg on prim:%x \n",frm->prim); + + free_msg(msg); return 1; #endif } else { - cb_log(0, stack->port, "NO BC FOR STACK: port:%d\n", frm->addr&IF_CONTRMASK); + cb_log(0, stack->port, "NO BC FOR STACK\n"); } - } - cb_log(4, stack->port, "TE_FRM_HANDLER: Returning 0 on prim:%x port:%d\n",frm->prim, frm->addr&IF_CONTRMASK); - + + cb_log(4, stack->port, "TE_FRM_HANDLER: Returning 0 on prim:%x \n",frm->prim); return 0; } @@ -2110,21 +2619,24 @@ int handle_frm(msg_t *msg) int handle_l1(msg_t *msg) { iframe_t *frm = (iframe_t*) msg->data; - struct misdn_stack *stack = find_stack_by_port(frm->addr & IF_CONTRMASK); + struct misdn_stack *stack = find_stack_by_addr(frm->addr); int i ; if (!stack) return 0 ; - + switch (frm->prim) { case PH_ACTIVATE | CONFIRM: case PH_ACTIVATE | INDICATION: - cb_log (1, stack->port, "L1: PH L1Link Up! port:%d\n",stack->port); + cb_log (3, stack->port, "L1: PH L1Link Up!\n"); stack->l1link=1; - if (stack->mode==NT_MODE) { + if (stack->nt) { if (stack->nst.l1_l2(&stack->nst, msg)) free_msg(msg); + + if (stack->ptp) + misdn_lib_get_l2_up(stack); } else { free_msg(msg); } @@ -2137,30 +2649,37 @@ int handle_l1(msg_t *msg) } } + return 1; + + case PH_ACTIVATE | REQUEST: + free_msg(msg); + cb_log(3,stack->port,"L1: PH_ACTIVATE|REQUEST \n"); + return 1; + case PH_DEACTIVATE | REQUEST: + free_msg(msg); + cb_log(3,stack->port,"L1: PH_DEACTIVATE|REQUEST \n"); return 1; + case PH_DEACTIVATE | CONFIRM: case PH_DEACTIVATE | INDICATION: - cb_log (1, stack->port, "L1: PH L1Link Down! port:%d\n",stack->port); + cb_log (3, stack->port, "L1: PH L1Link Down! \n"); for (i=0; i<stack->b_num; i++) { if (global_state == MISDN_INITIALIZED) { cb_event(EVENT_CLEANUP, &stack->bc[i], glob_mgr->user_data); } - } - if (stack->mode==NT_MODE) { + if (stack->nt) { if (stack->nst.l1_l2(&stack->nst, msg)) free_msg(msg); - } else { free_msg(msg); } stack->l1link=0; stack->l2link=0; - return 1; } @@ -2170,39 +2689,30 @@ int handle_l1(msg_t *msg) int handle_l2(msg_t *msg) { iframe_t *frm = (iframe_t*) msg->data; - struct misdn_stack *stack = find_stack_by_addr(frm->addr & IF_ADDRMASK); - if (!stack) return 0 ; - + struct misdn_stack *stack = find_stack_by_addr(frm->addr); + + if (!stack) { + return 0 ; + } + switch(frm->prim) { -#ifdef DL_STATUS - case DL_STATUS | INDICATION: - case DL_STATUS | CONFIRM: - cb_log (3, stack->port, "L2: DL_STATUS! port:%d\n", stack->port); + case DL_ESTABLISH | REQUEST: + cb_log(1,stack->port,"DL_ESTABLISH|REQUEST \n"); + return 1; + case DL_RELEASE | REQUEST: + cb_log(1,stack->port,"DL_RELEASE|REQUEST \n"); + return 1; - switch (frm->dinfo) { - case SDL_ESTAB: - cb_log (4, stack->port, " --> SDL_ESTAB port:%d\n", stack->port); - stack->l1link=1; - goto dl_estab; - case SDL_REL: - cb_log (4, stack->port, " --> SDL_REL port:%d\n", stack->port); - stack->l1link=0; - misdn_lib_get_l2_up(stack); - goto dl_rel; - } - break; -#endif - - case DL_ESTABLISH | INDICATION: case DL_ESTABLISH | CONFIRM: -#ifdef DL_STATUS - dl_estab: -#endif { - cb_log (3, stack->port, "L2: L2Link Up! port:%d\n", stack->port); + cb_log (3, stack->port, "L2: L2Link Up! \n"); + if (stack->ptp && stack->l2link) { + cb_log (-1, stack->port, "L2: L2Link Up! but it's already UP.. must be faulty, blocking port\n"); + cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data); + } stack->l2link=1; free_msg(msg); return 1; @@ -2211,11 +2721,8 @@ int handle_l2(msg_t *msg) case DL_RELEASE | INDICATION: case DL_RELEASE | CONFIRM: -#ifdef DL_STATUS - dl_rel: -#endif { - cb_log (3, stack->port, "L2: L2Link Down! port:%d\n", stack->port); + cb_log (3, stack->port, "L2: L2Link Down! \n"); stack->l2link=0; free_msg(msg); @@ -2226,16 +2733,84 @@ int handle_l2(msg_t *msg) return 0; } - int handle_mgmt(msg_t *msg) { iframe_t *frm = (iframe_t*) msg->data; - - if ( (frm->prim & 0x0f0000) == 0x0f0000) { - cb_log(5, 0, "$$$ MGMT FRAME: prim %x addr %x dinfo %x\n",frm->prim, frm->addr, frm->dinfo) ; + + if ( (frm->addr == 0) && (frm->prim == (MGR_DELLAYER|CONFIRM)) ) { + cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: 0 !\n") ; free_msg(msg); return 1; } + + struct misdn_stack * stack=find_stack_by_addr(frm->addr); + + if (!stack) { + if (frm->prim == (MGR_DELLAYER|CONFIRM)) { + cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: %x !\n", + frm->addr) ; + free_msg(msg); + return 1; + } + + return 0; + } + + switch(frm->prim) { + case MGR_SHORTSTATUS | INDICATION: + case MGR_SHORTSTATUS | CONFIRM: + cb_log(5, stack->port, "MGMT: Short status dinfo %x\n",frm->dinfo); + switch (frm->dinfo) { + case SSTATUS_L1_ACTIVATED: + cb_log(3, stack->port, "MGMT: SSTATUS: L1_ACTIVATED \n"); + stack->l1link=1; + break; + + case SSTATUS_L1_DEACTIVATED: + cb_log(3, stack->port, "MGMT: SSTATUS: L1_DEACTIVATED \n"); + /*reopen L1 if down*/ + if (stack->l1link==2) + stack->l1link--; + else + stack->l1link=0; + + clear_l3(stack); + + break; + + case SSTATUS_L2_ESTABLISHED: + cb_log(3, stack->port, "MGMT: SSTATUS: L2_ESTABLISH \n"); + stack->l2link=1; + if ( !stack->ptp && !stack->nt ) + stack->l1link=2; + break; + + case SSTATUS_L2_RELEASED: + cb_log(3, stack->port, "MGMT: SSTATUS: L2_RELEASED \n"); + stack->l2link=0; + break; + } + + free_msg(msg); + return 1; + + case MGR_SETSTACK | INDICATION: + cb_log(4, stack->port, "MGMT: SETSTACK|IND dinfo %x\n",frm->dinfo); + free_msg(msg); + return 1; + case MGR_DELLAYER | CONFIRM: + cb_log(4, stack->port, "MGMT: DELLAYER|CNF dinfo %x\n",frm->dinfo) ; + free_msg(msg); + return 1; + + } + + /* + if ( (frm->prim & 0x0f0000) == 0x0f0000) { + cb_log(5, 0, "$$$ MGMT FRAME: prim %x addr %x dinfo %x\n",frm->prim, frm->addr, frm->dinfo) ; + free_msg(msg); + return 1; + } */ return 0; } @@ -2245,33 +2820,51 @@ msg_t *fetch_msg(int midev) { msg_t *msg=alloc_msg(MAX_MSG_SIZE); int r; - fd_set rdfs; +/* fd_set rdfs; */ if (!msg) { cb_log(0, 0, "fetch_msg: alloc msg failed !!"); return NULL; } - + +#if 0 FD_ZERO(&rdfs); FD_SET(midev,&rdfs); mISDN_select(FD_SETSIZE, &rdfs, NULL, NULL, NULL); + //select(FD_SETSIZE, &rdfs, NULL, NULL, NULL); if (FD_ISSET(midev, &rdfs)) { - - r=mISDN_read(midev,msg->data,MAX_MSG_SIZE,0); +#endif + + AGAIN: + r=mISDN_read(midev,msg->data,MAX_MSG_SIZE, TIMEOUT_10SEC); msg->len=r; if (r==0) { free_msg(msg); /* danger, cauz usualy freeing in main_loop */ - printf ("Got empty Msg?\n"); + cb_log(6,0,"Got empty Msg..\n"); return NULL; } + if (r<0) { + if (errno == EAGAIN) { + /*we wait for mISDN here*/ + cb_log(4,0,"mISDN_read wants us to wait\n"); + usleep(5000); + goto AGAIN; + } + + cb_log(0,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno); + } + return msg; + +#if 0 } else { printf ("Select timeout\n"); } +#endif return NULL; } @@ -2282,9 +2875,7 @@ static void misdn_lib_isdn_event_catcher(void *arg) struct misdn_lib *mgr = arg; int zero_frm=0 , fff_frm=0 ; int midev= mgr->midev; - int port; - - //cb_log(5, 0, "In event_catcher thread\n"); + int port=0; while (1) { msg_t *msg = fetch_msg(midev); @@ -2294,7 +2885,6 @@ static void misdn_lib_isdn_event_catcher(void *arg) if (!msg) continue; frm = (iframe_t*) msg->data; - port = frm->addr&IF_CONTRMASK; /** When we make a call from NT2Ast we get this frames **/ if (frm->len == 0 && frm->addr == 0 && frm->dinfo == 0 && frm->prim == 0 ) { @@ -2397,41 +2987,92 @@ struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc) +void prepare_bc(struct misdn_bchannel*bc, int channel) +{ + bc->channel = channel; + bc->channel_preselected = channel?1:0; + bc->in_use = 1; + bc->need_disconnect=1; + bc->need_release=1; + bc->need_release_complete=1; + bc->cause=16; + + if (++mypid>5000) mypid=1; + bc->pid=mypid; + +#if 0 + bc->addr=0; + bc->b_stid=0; + bc->layer_id=0; +#endif +} + struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel) { struct misdn_stack *stack; int i; - if (channel < 0 || channel > MAX_BCHANS) + if (channel < 0 || channel > MAX_BCHANS) { + cb_log(0,port,"Requested channel out of bounds (%d)\n",channel); return NULL; + } for (stack=glob_mgr->stack_list; stack; stack=stack->next) { if (stack->port == port) { + if (stack->blocked) { + cb_log(0,port,"Port is blocked\n"); + return NULL; + } + if (channel > 0) { if (channel <= stack->b_num) { for (i = 0; i < stack->b_num; i++) { if (stack->bc[i].in_use && stack->bc[i].channel == channel) { + cb_log(0,port,"Requested channel:%d on port:%d is already in use\n",channel, port); return NULL; } } - } else + } else { + cb_log(0,port,"Requested channel:%d is out of bounds on port:%d\n",channel, port); return NULL; + } } for (i = 0; i < stack->b_num; i++) { if (!stack->bc[i].in_use) { - stack->bc[i].channel = channel; - stack->bc[i].channel_preselected = channel?1:0; - stack->bc[i].in_use = 1; + prepare_bc(&stack->bc[i], channel); return &stack->bc[i]; } } + + cb_log(1,port,"There is no free channel on port (%d)\n",port); return NULL; } } + + cb_log(0,port,"Port is not configured (%d)\n",port); return NULL; } + +char *fac2str (enum facility_type type) { + struct arr_el { + enum facility_type p; + char *s ; + } arr[] = { + { FACILITY_NONE, "FAC_NONE" }, + { FACILITY_CALLDEFLECT, "FAC_CALLDEFLECT"}, + { FACILITY_CENTREX, "FAC_CENTREX"} + }; + + int i; + + for (i=0; i < sizeof(arr)/sizeof( struct arr_el) ; i ++) + if ( arr[i].p==type) return arr[i].s; + + return "FAC_UNKNOWN"; +} + void misdn_lib_log_ies(struct misdn_bchannel *bc) { if (!bc) return; @@ -2439,96 +3080,120 @@ void misdn_lib_log_ies(struct misdn_bchannel *bc) struct misdn_stack *stack=get_stack_by_bc(bc); if (!stack) return; - - cb_log(2, stack->port, " --> mode:%s cause:%d ocause:%d rad:%s\n", stack->mode==NT_MODE?"NT":"TE", bc->cause, bc->out_cause, bc->rad); + + cb_log(2, stack->port, " --> channel:%d mode:%s cause:%d ocause:%d rad:%s cad:%s\n", bc->channel, stack->nt?"NT":"TE", bc->cause, bc->out_cause, bc->rad, bc->cad); cb_log(2, stack->port, - " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c\n", + " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c cpnnumplan:%c\n", bc->info_dad, bc->onumplan>=0?'0'+bc->onumplan:' ', bc->dnumplan>=0?'0'+bc->dnumplan:' ', - bc->rnumplan>=0?'0'+bc->rnumplan:' ' + bc->rnumplan>=0?'0'+bc->rnumplan:' ', + bc->cpnnumplan>=0?'0'+bc->cpnnumplan:' ' ); - cb_log(2, stack->port, " --> channel:%d caps:%s pi:%x keypad:%s\n", bc->channel, bearer2str(bc->capability),bc->progress_indicator, bc->keypad); - - cb_log(3, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1); + cb_log(3, stack->port, " --> caps:%s pi:%x keypad:%s sending_complete:%d\n", bearer2str(bc->capability),bc->progress_indicator, bc->keypad, bc->sending_complete); + cb_log(4, stack->port, " --> screen:%d --> pres:%d\n", + bc->screen, bc->pres); - cb_log(3, stack->port, " --> pid:%d addr:%x l3id:%x\n", bc->pid, bc->addr, bc->l3_id); + cb_log(4, stack->port, " --> addr:%x l3id:%x b_stid:%x layer_id:%x\n", bc->addr, bc->l3_id, bc->b_stid, bc->layer_id); + + cb_log(4, stack->port, " --> facility:%s out_facility:%s\n",fac2str(bc->fac_type),fac2str(bc->out_fac_type)); - cb_log(4, stack->port, " --> bc:%x h:%d sh:%d\n", bc, bc->holded, bc->stack_holder); + cb_log(5, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1); + + cb_log(5, stack->port, " --> bc:%x h:%d sh:%d\n", bc, bc->holded, bc->stack_holder); } int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) { msg_t *msg; int err = -1 ; + int ret=0; if (!bc) goto ERR; struct misdn_stack *stack=get_stack_by_bc(bc); - if ( stack->mode == NT_MODE && !stack->l1link) { + if (!stack) { + cb_log(0,bc->port,"SENDEVENT: no Stack for event:%s oad:%s dad:%s \n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad); + return -1; + } + + cb_log(6,stack->port,"SENDEVENT: stack->nt:%d stack->uperid:%x\n",stack->nt, stack->upper_id); + + if ( stack->nt && !stack->l1link) { /** Queue Event **/ bc->evq=event; cb_log(1, stack->port, "Queueing Event %s because L1 is down (btw. Activating L1)\n", isdn_get_info(msgs_g, event, 0)); - { /* Pull Up L1 */ - iframe_t act; - act.prim = PH_ACTIVATE | REQUEST; - act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ; - act.dinfo = 0; - act.len = 0; - mISDN_write(glob_mgr->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC); - } - + misdn_lib_get_l1_up(stack); return 0; } - cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s port:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, stack->port); + cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s pid:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, bc->pid); + cb_log(1, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state)); misdn_lib_log_ies(bc); switch (event) { case EVENT_SETUP: if (create_process(glob_mgr->midev, bc)<0) { cb_log(0, stack->port, " No free channel at the moment @ send_event\n"); + err=-ENOCHAN; goto ERR; } +#if 0 + if (stack->nt) { + ret=setup_bc(bc); + if (ret == -EINVAL) { + cb_log(0,bc->port,"send_event: setup_bc failed\n"); + } + } +#endif break; - case EVENT_CONNECT: case EVENT_PROGRESS: case EVENT_ALERTING: case EVENT_PROCEEDING: case EVENT_SETUP_ACKNOWLEDGE: + if (!bc->nt && !stack->ptp) break; + + case EVENT_CONNECT: case EVENT_RETRIEVE_ACKNOWLEDGE: + + bc->holded=0; - if (stack->mode == NT_MODE) { + if (stack->nt) { if (bc->channel <=0 ) { /* else we have the channel already */ bc->channel = find_free_chan_in_stack(stack, 0); if (!bc->channel) { cb_log(0, stack->port, " No free channel at the moment\n"); + err=-ENOCHAN; goto ERR; } } /* Its that i generate channels */ } + + ret=setup_bc(bc); + if (ret == -EINVAL) { + cb_log(0,bc->port,"send_event: setup_bc failed\n"); + } + + cb_log(0,bc->port,"After SETUP BC\n"); + - setup_bc(bc); - - - if ( event == EVENT_CONNECT ) { - if ( *bc->crypt_key ) { - cb_log(4, stack->port, " --> ENABLING BLOWFISH port:%d channel:%d oad%d:%s dad%d:%s \n", stack->port, bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad); + if (misdn_cap_is_speech(bc->capability)) { + if ((event==EVENT_CONNECT)||(event==EVENT_RETRIEVE_ACKNOWLEDGE)) { + if ( *bc->crypt_key ) { + cb_log(4, stack->port, " --> ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad); + + manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) ); + } - manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) ); - } - - if ( misdn_cap_is_speech(bc->capability)) { if (!bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0); - - if (bc->ec_enable) manager_ec_enable(bc); + manager_ec_enable(bc); if (bc->txgain != 0) { cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain); @@ -2541,50 +3206,78 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) } } } - - if (event == EVENT_RETRIEVE_ACKNOWLEDGE) { - manager_bchannel_activate(bc); - } - break; - + case EVENT_HOLD_ACKNOWLEDGE: { struct misdn_bchannel *holded_bc=malloc(sizeof(struct misdn_bchannel)); - memcpy(holded_bc,bc,sizeof(struct misdn_bchannel)); - holded_bc->holded=1; stack_holder_add(stack,holded_bc); - if (stack->mode == NT_MODE) { - empty_chan_in_stack(stack,bc->channel); + if (stack->nt) { + if (bc->bc_state == BCHAN_BRIDGED) { + misdn_split_conf(bc,bc->conf_id); + misdn_split_conf(bc->holded_bc,bc->holded_bc->conf_id); + } + + if (bc->channel>0) + empty_chan_in_stack(stack,bc->channel); empty_bc(bc); clean_up_bc(bc); } /** we set it up later at RETRIEVE_ACK again.**/ - holded_bc->upset=0; - holded_bc->active=0; + /*holded_bc->upset=0; + holded_bc->active=0;*/ + bc_state_change(holded_bc,BCHAN_CLEANED); - cb_event( EVENT_NEW_BC, holded_bc, glob_mgr->user_data); + cb_event( EVENT_NEW_BC, bc, holded_bc); } break; - + + /* finishing the channel eh ? */ + case EVENT_DISCONNECT: + if (!bc->need_disconnect) { + cb_log(0,bc->port," --> we have already send Disconnect\n"); + return -1; + } + + bc->need_disconnect=0; + break; case EVENT_RELEASE: + if (!bc->need_release) { + cb_log(0,bc->port," --> we have already send Release\n"); + return -1; + } + bc->need_disconnect=0; + bc->need_release=0; break; - case EVENT_RELEASE_COMPLETE: - empty_chan_in_stack(stack,bc->channel); - empty_bc(bc); - clean_up_bc(bc); + if (!bc->need_release_complete) { + cb_log(0,bc->port," --> we have already send Release_complete\n"); + return -1; + } + bc->need_disconnect=0; + bc->need_release=0; + bc->need_release_complete=0; break; case EVENT_CONNECT_ACKNOWLEDGE: + + if ( bc->nt || misdn_cap_is_speech(bc->capability)) { + int ret=setup_bc(bc); + if (ret == -EINVAL){ + cb_log(0,bc->port,"send_event: setup_bc failed\n"); + + } + } + if (misdn_cap_is_speech(bc->capability)) { if ( !bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0); - if (bc->ec_enable) manager_ec_enable(bc); + manager_ec_enable(bc); + if ( bc->txgain != 0 ) { cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain); manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain); @@ -2601,7 +3294,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) } /* Later we should think about sending bchannel data directly to misdn. */ - msg = isdn_msg_build_event(msgs_g, bc, event, stack->mode==NT_MODE?1:0); + msg = isdn_msg_build_event(msgs_g, bc, event, stack->nt); msg_queue_tail(&stack->downqueue, msg); sem_post(&glob_mgr->new_msg); @@ -2612,40 +3305,151 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) } +int handle_err(msg_t *msg) +{ + iframe_t *frm = (iframe_t*) msg->data; + + + if (!frm->addr) { + static int cnt=0; + if (!cnt) + cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x\n",frm->prim,frm->dinfo); + cnt++; + if (cnt>100) { + cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x (already more than 100 of them)\n",frm->prim,frm->dinfo); + cnt=0; + } + + free_msg(msg); + return 1; + + } + + switch (frm->prim) { + case MGR_SETSTACK|INDICATION: + return handle_bchan(msg); + break; + + case MGR_SETSTACK|CONFIRM: + case MGR_CLEARSTACK|CONFIRM: + free_msg(msg) ; + return 1; + break; + + case DL_DATA|CONFIRM: + cb_log(4,0,"DL_DATA|CONFIRM\n"); + free_msg(msg); + return 1; + + case PH_CONTROL|CONFIRM: + cb_log(4,0,"PH_CONTROL|CONFIRM\n"); + free_msg(msg); + return 1; + + case DL_DATA|INDICATION: + { + int port=(frm->addr&MASTER_ID_MASK) >> 8; + int channel=(frm->addr&CHILD_ID_MASK) >> 16; + + /*we flush the read buffer here*/ + + cb_log(9,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel); + + free_msg(msg) ; + return 1; + + + struct misdn_bchannel *bc=find_bc_by_channel( port , channel); + + if (!bc) { + struct misdn_stack *stack=find_stack_by_port( port ); + + if (!stack) { + cb_log(0,0," --> stack not found\n"); + free_msg(msg); + return 1; + } + + cb_log(0,0," --> bc not found by channel\n"); + if (stack->l2link) + misdn_lib_get_l2_down(stack); + + if (stack->l1link) + misdn_lib_get_l1_down(stack); + + free_msg(msg); + return 1; + } + + cb_log(3,port," --> BC in state:%s\n", bc_state2str(bc->bc_state)); + } + } + + return 0; +} + + +int queue_l2l3(msg_t *msg) { + iframe_t *frm= (iframe_t*)msg->data; + struct misdn_stack *stack; + stack=find_stack_by_addr( frm->addr ); + + + if (!stack) { + return 0; + } + + msg_queue_tail(&stack->upqueue, msg); + sem_post(&glob_mgr->new_msg); + return 1; +} int manager_isdn_handler(iframe_t *frm ,msg_t *msg) { if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM)) { - printf("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n"); + cb_log(0,0,"SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n"); } + if ( ((frm->addr | ISDN_PID_BCHANNEL_BIT )>> 28 ) == 0x5) { + if (handle_bchan(msg)) { + return 0 ; + } + } + +#ifdef RECV_FRM_SYSLOG_DEBUG + syslog(LOG_NOTICE,"mISDN recv: P(%02d): ADDR:%x PRIM:%x DINFO:%x\n",stack->port, frm->addr, frm->prim, frm->dinfo); +#endif + if (handle_timers(msg)) return 0 ; - - if (handle_mgmt(msg)) - return 0 ; + + if (handle_mgmt(msg)) + return 0 ; + if (handle_l2(msg)) return 0 ; /* Its important to handle l1 AFTER l2 */ if (handle_l1(msg)) return 0 ; + + if (handle_frm_nt(msg)) { + return 0; + } - if (handle_bchan(msg)) - return 0 ; + if (handle_frm(msg)) { + return 0; + } - /** Handle L2/3 Signalling after bchans **/ - if (handle_frm_nt(msg)) - return 0 ; - - if (handle_frm(msg)) + if (handle_err(msg)) { return 0 ; + } - cb_log(0, frm->addr&IF_CONTRMASK, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on port: %d\n",frm->prim, frm->len, frm->addr, frm->dinfo, frm->addr&IF_CONTRMASK); - + cb_log(0, 0, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo); free_msg(msg); + return 0; } @@ -2664,12 +3468,14 @@ int misdn_lib_get_port_info(int port) } frm=(iframe_t*)msg->data; if (!stack ) { - cb_log(0, port, "There is no Stack on Port:%d\n",port); + cb_log(0, port, "There is no Stack for this port.\n"); return -1; } /* activate bchannel */ frm->prim = CC_STATUS_ENQUIRY | REQUEST; - frm->addr = stack->upper_id; + + frm->addr = stack->upper_id| FLG_MSG_DOWN; + frm->dinfo = 0; frm->len = 0; @@ -2680,80 +3486,65 @@ int misdn_lib_get_port_info(int port) return 0; } + +int queue_cleanup_bc(struct misdn_bchannel *bc) +{ + msg_t *msg=alloc_msg(MAX_MSG_SIZE); + iframe_t *frm; + if (!msg) { + cb_log(0, bc->port, "misgn_lib_get_port: alloc_msg failed!\n"); + return -1; + } + frm=(iframe_t*)msg->data; + + /* activate bchannel */ + frm->prim = MGR_CLEARSTACK| REQUEST; + + frm->addr = bc->l3_id; + + frm->dinfo = bc->port; + frm->len = 0; + + msg_queue_tail(&glob_mgr->activatequeue, msg); + sem_post(&glob_mgr->new_msg); + + return 0; + +} + int misdn_lib_port_restart(int port) { struct misdn_stack *stack=find_stack_by_port(port); - cb_log(0, port, "Restarting Port:%d\n",port); + cb_log(0, port, "Restarting this port.\n"); if (stack) { cb_log(0, port, "Stack:%p\n",stack); - - + clear_l3(stack); - { msg_t *msg=alloc_msg(MAX_MSG_SIZE); iframe_t *frm; if (!msg) { - cb_log(0, port, "port_restart: alloc_msg fialed\n"); + cb_log(0, port, "port_restart: alloc_msg failed\n"); return -1; } frm=(iframe_t*)msg->data; /* we must activate if we are deactivated */ /* activate bchannel */ - frm->prim = DL_RELEASE | REQUEST; - - frm->addr = stack->upper_id ; + frm->addr = stack->upper_id | FLG_MSG_DOWN; + frm->dinfo = 0; frm->len = 0; msg_queue_tail(&glob_mgr->activatequeue, msg); sem_post(&glob_mgr->new_msg); } - return 0; - - stack_te_destroy(stack); - - { - struct misdn_stack *tmpstack; - struct misdn_stack *newstack=stack_te_init(stack->midev ,port, stack->ptp); - - - if (stack == glob_mgr->stack_list) { - struct misdn_stack *n=glob_mgr->stack_list->next; - glob_mgr->stack_list = newstack ; - glob_mgr->stack_list->next = n; - } else { - for (tmpstack=glob_mgr->stack_list; - tmpstack->next; - tmpstack=tmpstack->next) - if (tmpstack->next == stack) break; - if (!tmpstack->next) { - cb_log(0, port, "Stack to restart not found\n"); - return 0; - } else { - struct misdn_stack *n=tmpstack->next->next; - tmpstack->next=newstack; - newstack->next=n; - } - } - - { - int i; - for(i=0;i<newstack->b_num; i++) { - int r; - if ((r=init_bc(newstack, &newstack->bc[i], newstack->midev,port,i, "", 1))<0) { - cb_log(0, port, "Got Err @ init_bc :%d\n",r); - return 0; - } - } - } - - free(stack); - } + if (stack->nt) + misdn_lib_reinit_nt_stack(stack->port); + } return 0; @@ -2782,6 +3573,27 @@ void manager_event_handler(void *arg) iframe_t *frm = (iframe_t*) msg->data ; switch ( frm->prim) { + + case MGR_CLEARSTACK | REQUEST: + /*a queued bchannel cleanup*/ + { + struct misdn_stack *stack=find_stack_by_port(frm->dinfo); + if (!stack) { + cb_log(0,0,"no stack found with port [%d]!! so we cannot cleanup the bc\n",frm->dinfo); + free_msg(msg); + break; + } + + struct misdn_bchannel *bc=find_bc_by_l3id(stack,frm->addr); + if (bc) { + cb_log(1,bc->port,"CLEARSTACK queued, cleaning up\n"); + clean_up_bc(bc); + } else { + cb_log(0,stack->port,"bc could not be cleaned correctly !! addr [%x]\n",frm->addr); + } + } + free_msg(msg); + break; case MGR_SETSTACK | REQUEST : break; default: @@ -2793,20 +3605,32 @@ void manager_event_handler(void *arg) for (stack=glob_mgr->stack_list; stack; stack=stack->next ) { + + while ( (msg=msg_dequeue(&stack->upqueue)) ) { + /** Handle L2/3 Signalling after bchans **/ + if (!handle_frm_nt(msg)) { + /* Maybe it's TE */ + if (!handle_frm(msg)) { + /* wow none! */ + cb_log(0,stack->port,"Wow we've got a strange issue while dequeueing a Frame\n"); + } + } + } + + /* Here we should check if we really want to + send all the messages we've queued, lets + assume we've queued a Disconnect, but + received it already from the other side!*/ + while ( (msg=msg_dequeue(&stack->downqueue)) ) { - - if (stack->mode == NT_MODE ){ - + if (stack->nt ) { if (stack->nst.manager_l3(&stack->nst, msg)) cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n"); } else { - if (msg) { - iframe_t *frm = (iframe_t *)msg->data; - struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo); - - if (bc) send_msg(glob_mgr->midev, bc, msg); - } + iframe_t *frm = (iframe_t *)msg->data; + struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo); + if (bc) send_msg(glob_mgr->midev, bc, msg); } } } @@ -2829,6 +3653,27 @@ int misdn_lib_maxports_get() { /** BE AWARE WE HAVE NO CB_LOG HERE! **/ return max; } + +void misdn_lib_nt_debug_init( int flags, char *file ) +{ + int static init=0; + char *f; + + if (!flags) + f=NULL; + else + f=file; + + if (!init) { + debug_init( flags , f, f, f); + init=1; + } else { + debug_close(); + debug_init( flags , f, f, f); + } +} + + int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_data) { struct misdn_lib *mgr=calloc(1, sizeof(struct misdn_lib)); @@ -2839,12 +3684,13 @@ int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_dat cb_log = iface->cb_log; cb_event = iface->cb_event; - cb_clearl3_true = iface->cb_clearl3_true; + cb_jb_empty = iface->cb_jb_empty; glob_mgr = mgr; msg_init(); - debug_init(0 , NULL, NULL, NULL); + + misdn_lib_nt_debug_init(0,NULL); if (!portlist || (*portlist == 0) ) return 1; @@ -2883,12 +3729,10 @@ int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_dat ptp=1; if (port > port_count) { - cb_log(0, port, "Couldn't Initialize Port:%d since we have only %d ports\n",port, port_count); + cb_log(0, port, "Couldn't Initialize this port since we have only %d ports\n", port_count); exit(1); } - stack=stack_te_init(midev, port, ptp); - - + stack=stack_init(midev, port, ptp); if (!stack) { perror("init_stack"); @@ -2937,22 +3781,20 @@ int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_dat if (sem_init(&handler_started, 1, 0)<0) sem_init(&handler_started, 0, 0); - cb_log(4, 0, "Starting Event Handler\n"); + cb_log(8, 0, "Starting Event Handler\n"); pthread_create( &mgr->event_handler_thread, NULL,(void*)manager_event_handler, mgr); sem_wait(&handler_started) ; - cb_log(4, 0, "Starting Event Catcher\n"); + cb_log(8, 0, "Starting Event Catcher\n"); pthread_create( &mgr->event_thread, NULL, (void*)misdn_lib_isdn_event_catcher, mgr); - cb_log(4, 0, "Event Catcher started\n"); + cb_log(8, 0, "Event Catcher started\n"); global_state= MISDN_INITIALIZED; return (mgr == NULL); } - - void misdn_lib_destroy() { struct misdn_stack *help; @@ -2961,14 +3803,11 @@ void misdn_lib_destroy() for ( help=glob_mgr->stack_list; help; help=help->next ) { for(i=0;i<help->b_num; i++) { char buf[1024]; - mISDN_write_frame(help->midev, buf, help->bc[i].addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); help->bc[i].addr = 0; } - - - cb_log (1, help->port, "Destroying port:%d\n", help->port); - stack_te_destroy(help); + cb_log (1, help->port, "Destroying this port.\n"); + stack_destroy(help); } if (global_state == MISDN_INITIALIZED) { @@ -2978,7 +3817,6 @@ void misdn_lib_destroy() pthread_join(glob_mgr->event_handler_thread, NULL); } - cb_log(4, 0, "Killing Main Thread\n"); if ( pthread_cancel(glob_mgr->event_thread) == 0 ) { cb_log(4, 0, "Joining Main Thread\n"); @@ -2990,48 +3828,42 @@ void misdn_lib_destroy() te_lib_destroy(glob_mgr->midev); } - char *manager_isdn_get_info(enum event_e event) { return isdn_get_info(msgs_g , event, 0); } - - - void manager_bchannel_activate(struct misdn_bchannel *bc) { - msg_t *msg=alloc_msg(MAX_MSG_SIZE); - iframe_t *frm; + char buf[128]; + iframe_t *ifrm; + int ret; struct misdn_stack *stack=get_stack_by_bc(bc); - - if (!msg) { - cb_log(0, stack->port, "bchannel_activate: alloc_msg failed !"); + + if (!stack) { + cb_log(0, bc->port, "bchannel_activate: Stack not found !"); return ; } - frm=(iframe_t*)msg->data; /* we must activate if we are deactivated */ - clear_ibuffer(bc->misdnbuf); clear_ibuffer(bc->astbuf); - - if (bc->active) return; - cb_log(5, stack->port, "$$$ Bchan Activated addr %x\n", bc->addr); - - /* activate bchannel */ - frm->prim = DL_ESTABLISH | REQUEST; - frm->addr = bc->addr ; - frm->dinfo = 0; - frm->len = 0; - msg_queue_tail(&glob_mgr->activatequeue, msg); - sem_post(&glob_mgr->new_msg); + mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_ESTABLISH | REQUEST, 0,0, NULL, TIMEOUT_1SEC); - bc->active=1; - + ret=mISDN_read(stack->midev,buf,128,TIMEOUT_10SEC); + + ifrm=(iframe_t*)buf; + + if (ret>0) { + if (ifrm->prim== (DL_ESTABLISH|CONFIRM)) { + cb_log(2,stack->port,"bchan: DL_ESTABLISH|CNF\n"); + } + } + + return ; } @@ -3039,96 +3871,106 @@ void manager_bchannel_activate(struct misdn_bchannel *bc) void manager_bchannel_deactivate(struct misdn_bchannel * bc) { - iframe_t dact; struct misdn_stack *stack=get_stack_by_bc(bc); - if (!bc->active) return; - - cb_log(5, stack->port, "$$$ Bchan deActivated addr %x\n", bc->addr); - - bc->tone=TONE_NONE; + + switch (bc->bc_state) { + case BCHAN_ACTIVATED: + break; + case BCHAN_BRIDGED: + misdn_split_conf(bc,bc->conf_id); + break; + default: + cb_log( 4, bc->port,"bchan_deactivate: called but not activated\n"); + return ; + + } + + cb_log(5, stack->port, "$$$ Bchan deActivated addr %x\n", bc->addr); + + bc->generate_tone=0; + + iframe_t dact; dact.prim = DL_RELEASE | REQUEST; - dact.addr = bc->addr; + dact.addr = bc->addr | FLG_MSG_DOWN; dact.dinfo = 0; dact.len = 0; - - mISDN_write(stack->midev, &dact, mISDN_HEADER_LEN+dact.len, TIMEOUT_1SEC); - clear_ibuffer(bc->misdnbuf); + char buf[128]; + mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_RELEASE|REQUEST,0,0,NULL, TIMEOUT_1SEC); + + mISDN_read(stack->midev, buf, 128, TIMEOUT_1SEC); + clear_ibuffer(bc->astbuf); - bc->active=0; + + bc_state_change(bc,BCHAN_RELEASE); return; } -int manager_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len) +int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len) { - struct misdn_stack *stack=get_stack_by_bc(bc); - if (!bc->active) return -1; - if ( misdn_cap_is_speech(bc->capability) ) - flip_buf_bits(data,len); + switch (bc->bc_state) { + case BCHAN_ACTIVATED: + case BCHAN_BRIDGED: + break; + default: + cb_log(3, bc->port, "BC not yet activated (state:%s)\n",bc_state2str(bc->bc_state)); + return -1; + } - if ( !bc->nojitter && misdn_cap_is_speech(bc->capability) ) { - if (len > ibuf_freecount(bc->misdnbuf)) { - len=ibuf_freecount(bc->misdnbuf); - } - ibuf_memcpy_w(bc->misdnbuf, (unsigned char*)data, len); - } else { - char buf[4096 + mISDN_HEADER_LEN]; - iframe_t *frm= (iframe_t*)buf; - int r; - - frm->prim = DL_DATA|REQUEST; - frm->dinfo = 0; - frm->addr = bc->addr | IF_DOWN; - frm->len = len; - memcpy(&buf[mISDN_HEADER_LEN], data,len); - - - - if ( misdn_cap_is_speech(bc->capability)) - cb_log(4, stack->port, "Writing %d bytes\n",len); + char buf[4096 + mISDN_HEADER_LEN]; + iframe_t *frm= (iframe_t*)buf; + int r; + + frm->prim = DL_DATA|REQUEST; + frm->dinfo = 0; + frm->addr = bc->addr | FLG_MSG_DOWN ; + + frm->len = len; + memcpy(&buf[mISDN_HEADER_LEN], data,len); - cb_log(9, stack->port, "Wrinting %d bytes 2 mISDN\n",len); - r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_INFINIT); + if ( misdn_cap_is_speech(bc->capability) ) + flip_buf_bits( &buf[mISDN_HEADER_LEN], len); + else + cb_log(6, stack->port, "Writing %d data bytes\n",len); + + cb_log(9, stack->port, "Writing %d bytes 2 mISDN\n",len); + r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_INFINIT); +#ifdef ACK_HDLC + if (bc->hdlc && bc->ack_hdlc) { + cb_log(4,stack->port,"Awaiting Acknowledge [%d]\n",len); + sem_wait((sem_t*)bc->ack_hdlc); + cb_log(4,stack->port,"Acknowledged\n"); } - +#endif return 0; } - -void manager_send_tone (struct misdn_bchannel *bc, enum tone_e tone) -{ - if (tone != TONE_NONE) manager_bchannel_activate(bc); - bc->tone=tone; - bc->tone_cnt2=-1; - bc->tone_cnt=0; -} - - - /* * send control information to the channel (dsp-module) */ void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2) { - unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)]; + unsigned char buffer[mISDN_HEADER_LEN+ 2*sizeof(int)]; iframe_t *ctrl = (iframe_t *)buffer; /* preload data */ - unsigned long *d = (unsigned long *)&ctrl->data.p; - struct misdn_stack *stack=get_stack_by_bc(bc); + unsigned int *d = (unsigned int*)&ctrl->data.p; + /*struct misdn_stack *stack=get_stack_by_bc(bc);*/ + + cb_log(4,bc->port,"ph_control: c1:%x c2:%x\n",c1,c2); ctrl->prim = PH_CONTROL | REQUEST; - ctrl->addr = bc->addr; + ctrl->addr = bc->addr | FLG_MSG_DOWN; ctrl->dinfo = 0; - ctrl->len = sizeof(unsigned long)*2; + ctrl->len = sizeof(unsigned int)*2; *d++ = c1; *d++ = c2; - mISDN_write(stack->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC); + mISDN_write(glob_mgr->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC); } /* @@ -3138,16 +3980,16 @@ void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c { unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len]; iframe_t *ctrl = (iframe_t *)buffer; - unsigned long *d = (unsigned long *)&ctrl->data.p; - struct misdn_stack *stack=get_stack_by_bc(bc); + unsigned int *d = (unsigned int *)&ctrl->data.p; + /*struct misdn_stack *stack=get_stack_by_bc(bc);*/ ctrl->prim = PH_CONTROL | REQUEST; - ctrl->addr = bc->addr; + ctrl->addr = bc->addr | FLG_MSG_DOWN; ctrl->dinfo = 0; - ctrl->len = sizeof(unsigned long) + c2_len; + ctrl->len = sizeof(unsigned int) + c2_len; *d++ = c1; memcpy(d, c2, c2_len); - mISDN_write(stack->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC); + mISDN_write(glob_mgr->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC); } @@ -3157,10 +3999,8 @@ void manager_clean_bc(struct misdn_bchannel *bc ) { struct misdn_stack *stack=get_stack_by_bc(bc); - if (bc->state == STATE_CONNECTED) - misdn_lib_send_event(bc,EVENT_DISCONNECT); - - empty_chan_in_stack(stack, bc->channel); + if (bc->channel>0) + empty_chan_in_stack(stack, bc->channel); empty_bc(bc); misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); @@ -3188,6 +4028,7 @@ void stack_holder_add(struct misdn_stack *stack, struct misdn_bchannel *holder) help=help->next) { if (!help->next) { help->next=holder; + break; } } @@ -3199,6 +4040,8 @@ void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holde if (!holder->stack_holder) return; + holder->stack_holder=0; + cb_log(4,stack->port, "*HOLDER: remove %x\n",holder->l3_id); if (!stack || ! stack->holding) return; @@ -3241,35 +4084,78 @@ struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned lon +void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone) +{ + + switch(tone) { + case TONE_DIAL: + manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_DIALTONE); + break; + + case TONE_ALERTING: + manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_RINGING); + break; + + case TONE_HANGUP: + manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_HANGUP); + break; + + case TONE_NONE: + default: + manager_ph_control(bc, TONE_PATT_OFF, TONE_GERMAN_HANGUP); + } + + char buf[mISDN_HEADER_LEN+128]; + iframe_t *frm=(iframe_t*)buf; + memset(buf,0,mISDN_HEADER_LEN+128); + + frm->prim=DL_DATA|REQUEST; + frm->addr=bc->addr|FLG_MSG_DOWN; + frm->dinfo=0; + frm->len=128; + + mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC); +} + + void manager_ec_enable(struct misdn_bchannel *bc) { int ec_arr[2]; struct misdn_stack *stack=get_stack_by_bc(bc); - cb_log(1, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d training:%d\n",bc->ec_deftaps, bc->ec_training); - - switch (bc->ec_deftaps) { - case 4: - case 8: - case 16: - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - cb_log(4, stack->port, "Taps is %d\n",bc->ec_deftaps); - break; - default: - cb_log(0, stack->port, "Taps should be power of 2\n"); - bc->ec_deftaps=128; + cb_log(1, stack?stack->port:0,"ec_enable\n"); + + if (!misdn_cap_is_speech(bc->capability)) { + cb_log(1, stack?stack->port:0, " --> no speech? cannot enable EC\n"); + return; } - ec_arr[0]=bc->ec_deftaps; - ec_arr[1]=bc->ec_training; + if (bc->ec_enable) { + cb_log(1, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d training:%d\n",bc->ec_deftaps, bc->ec_training); + + switch (bc->ec_deftaps) { + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + cb_log(4, stack->port, "Taps is %d\n",bc->ec_deftaps); + break; + default: + cb_log(0, stack->port, "Taps should be power of 2\n"); + bc->ec_deftaps=128; + } - manager_ph_control_block(bc, ECHOCAN_ON, ec_arr, sizeof(ec_arr)); + ec_arr[0]=bc->ec_deftaps; + ec_arr[1]=0; + + manager_ph_control_block(bc, ECHOCAN_ON, ec_arr, sizeof(ec_arr)); + } } @@ -3278,8 +4164,17 @@ void manager_ec_disable(struct misdn_bchannel *bc) { struct misdn_stack *stack=get_stack_by_bc(bc); - cb_log(1, stack?stack->port:0, "Sending Control ECHOCAN_OFF\n"); - manager_ph_control(bc, ECHOCAN_OFF, 0); + cb_log(1, stack?stack->port:0,"ec_disable\n"); + + if (!misdn_cap_is_speech(bc->capability)) { + cb_log(1, stack?stack->port:0, " --> no speech? cannot disable EC\n"); + return; + } + + if ( bc->ec_enable) { + cb_log(1, stack?stack->port:0, "Sending Control ECHOCAN_OFF\n"); + manager_ph_control(bc, ECHOCAN_OFF, 0); + } } struct misdn_stack* get_misdn_stack() { @@ -3288,21 +4183,127 @@ struct misdn_stack* get_misdn_stack() { +void misdn_join_conf(struct misdn_bchannel *bc, int conf_id) +{ + bc_state_change(bc,BCHAN_BRIDGED); + manager_ph_control(bc, CMX_RECEIVE_OFF, 0); + manager_ph_control(bc, CMX_CONF_JOIN, conf_id); + + cb_log(1,bc->port, "Joining bc:%x in conf:%d\n",bc->addr,conf_id); + + char data[16]; + int len=15; + + memset(data,0,15); + + misdn_lib_tx2misdn_frm(bc, data, len); + +} + + +void misdn_split_conf(struct misdn_bchannel *bc, int conf_id) +{ + bc_state_change(bc,BCHAN_ACTIVATED); + manager_ph_control(bc, CMX_RECEIVE_ON, 0); + manager_ph_control(bc, CMX_CONF_SPLIT, conf_id); + + cb_log(1,bc->port, "Splitting bc:%x in conf:%d\n",bc->addr,conf_id); +} + void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2) { - manager_ph_control(bc1, CMX_RECEIVE_OFF, 0); - manager_ph_control(bc2, CMX_RECEIVE_OFF, 0); + int conf_id=bc1->pid +1; + + cb_log(1, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port); + + struct misdn_bchannel *bc_list[]={ + bc1,bc2,NULL + }; + struct misdn_bchannel **bc; + + for (bc=bc_list; *bc; *bc++) { + (*bc)->conf_id=conf_id; + cb_log(1, (*bc)->port, " --> bc_addr:%x\n",(*bc)->addr); - manager_ph_control(bc1, CMX_CONF_JOIN, (bc1->pid<<1) +1); - manager_ph_control(bc2, CMX_CONF_JOIN, (bc1->pid<<1) +1); + switch((*bc)->bc_state) { + case BCHAN_ACTIVATED: + misdn_join_conf(*bc,conf_id); + break; + default: + bc_next_state_change(*bc,BCHAN_BRIDGED); + break; + } + } } void misdn_lib_split_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2) { + + struct misdn_bchannel *bc_list[]={ + bc1,bc2,NULL + }; + struct misdn_bchannel **bc; + + for (bc=bc_list; *bc; *bc++) { + if ( (*bc)->bc_state == BCHAN_BRIDGED){ + misdn_split_conf( *bc, (*bc)->conf_id); + } else { + cb_log( 2, (*bc)->port, "BC not bridged (state:%s) so not splitting it\n",bc_state2str((*bc)->bc_state)); + } + } + +} + + + +void misdn_lib_echo(struct misdn_bchannel *bc, int onoff) +{ + cb_log(1,bc->port, " --> ECHO %s\n", onoff?"ON":"OFF"); + manager_ph_control(bc, onoff?CMX_ECHO_ON:CMX_ECHO_OFF, 0); +} + + + +void misdn_lib_reinit_nt_stack(int port) +{ + struct misdn_stack *stack=find_stack_by_port(port); - manager_ph_control(bc1, CMX_RECEIVE_ON, 0) ; - manager_ph_control(bc2, CMX_RECEIVE_ON, 0); + if (stack) { + stack->l2link=0; + stack->blocked=0; - manager_ph_control(bc1, CMX_CONF_SPLIT, (bc1->pid<<1) +1); - manager_ph_control(bc2, CMX_CONF_SPLIT, (bc1->pid<<1) +1); + cleanup_Isdnl3(&stack->nst); + cleanup_Isdnl2(&stack->nst); + + + memset(&stack->nst, 0, sizeof(net_stack_t)); + memset(&stack->mgr, 0, sizeof(manager_t)); + + stack->mgr.nst = &stack->nst; + stack->nst.manager = &stack->mgr; + + stack->nst.l3_manager = handle_event_nt; + stack->nst.device = glob_mgr->midev; + stack->nst.cardnr = port; + stack->nst.d_stid = stack->d_stid; + + stack->nst.feature = FEATURE_NET_HOLD; + if (stack->ptp) + stack->nst.feature |= FEATURE_NET_PTP; + if (stack->pri) + stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID; + + stack->nst.l1_id = stack->lower_id; + stack->nst.l2_id = stack->upper_id; + + msg_queue_init(&stack->nst.down_queue); + Isdnl2Init(&stack->nst); + Isdnl3Init(&stack->nst); + + if (!stack->ptp) + misdn_lib_get_l1_up(stack); + misdn_lib_get_l2_up(stack); + } } + + diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h index 28a4fe7b6..f79bc2ad0 100644 --- a/channels/misdn/isdn_lib.h +++ b/channels/misdn/isdn_lib.h @@ -14,36 +14,74 @@ #ifndef TE_LIB #define TE_LIB + /** For initialization usage **/ /* typedef int ie_nothing_t ;*/ /** end of init usage **/ +#ifdef WITH_BEROEC +typedef int beroec_t; -#define MAX_BCHANS 30 -enum bc_state_e { - STATE_NOTHING=0, - STATE_NULL, - STATE_CALL_INIT, - STATE_CONNECTED, - STATE_HOLD_ACKNOWLEDGE +enum beroec_type { + BEROEC_FULLBAND=0, + BEROEC_SUBBAND, + BEROEC_FASTSUBBAND }; +void beroec_init(void); +void beroec_exit(void); +beroec_t *beroec_new(int tail, enum beroec_type type, int anti_howl, + int tonedisable, int zerocoeff, int adapt, int nlp); + +void beroec_destroy(beroec_t *ec); +int beroec_cancel_alaw_chunk(beroec_t *ec, + char *send, + char *receive , + int len); + +int beroec_version(void); +#endif + + enum tone_e { TONE_NONE=0, TONE_DIAL, TONE_ALERTING, + TONE_FAR_ALERTING, TONE_BUSY, + TONE_HANGUP, + TONE_CUSTOM, TONE_FILE }; + + +#define MAX_BCHANS 30 + +enum bchannel_state { + BCHAN_CLEANED=0, + BCHAN_EMPTY, + BCHAN_SETUP, + BCHAN_SETUPED, + BCHAN_ACTIVE, + BCHAN_ACTIVATED, + BCHAN_BRIDGE, + BCHAN_BRIDGED, + BCHAN_RELEASE, + BCHAN_RELEASED, + BCHAN_CLEAN, + BCHAN_CLEAN_REQUEST, + BCHAN_ERROR +}; + + enum misdn_err_e { ENOCHAN=1 }; - enum mISDN_NUMBER_PLAN { NUMPLAN_UNINITIALIZED=-1, NUMPLAN_INTERNATIONAL=0x1, @@ -61,10 +99,11 @@ enum event_response_e { }; - enum event_e { EVENT_NOTHING, + EVENT_TONE_GENERATE, EVENT_BCHAN_DATA, + EVENT_BCHAN_ACTIVATED, EVENT_CLEANUP, EVENT_PROCEEDING, EVENT_PROGRESS, @@ -99,6 +138,7 @@ enum event_e { EVENT_DTMF_TONE, EVENT_NEW_L3ID, EVENT_NEW_BC, + EVENT_PORT_ALARM, EVENT_UNKNOWN }; @@ -144,9 +184,19 @@ enum layer_e { UNKNOWN }; + + +/** FACILITY STUFF **/ + enum facility_type { FACILITY_NONE, - FACILITY_CALLDEFLECT + FACILITY_CALLDEFLECT=0x91, + FACILITY_CENTREX=0x88 +}; + +union facility { + char calldeflect_nr[15]; + char cnip[256]; }; @@ -161,13 +211,21 @@ struct misdn_bchannel { /* int b_addr; */ int layer_id; - + void *ack_hdlc; + + int layer; + /*state stuff*/ + int need_disconnect; + int need_release; + int need_release_complete; + /** var stuff**/ int l3_id; int pid; int ces; - + + int restart_channel; int channel; int channel_preselected; @@ -180,8 +238,8 @@ struct misdn_bchannel { void *astbuf; + void *misdnbuf; - int te_choose_channel; int early_bconnect; @@ -190,6 +248,13 @@ struct misdn_bchannel { int dtmf; int send_dtmf; + /* get setup ack */ + int need_more_infos; + + /* may there be more infos ?*/ + int sending_complete; + + /* wether we should use jollys dsp or not */ int nodsp; @@ -199,13 +264,17 @@ struct misdn_bchannel { enum mISDN_NUMBER_PLAN dnumplan; enum mISDN_NUMBER_PLAN rnumplan; enum mISDN_NUMBER_PLAN onumplan; + enum mISDN_NUMBER_PLAN cpnnumplan; int progress_coding; int progress_location; int progress_indicator; - enum facility_type facility; - char facility_calldeflect_nr[15]; + enum facility_type fac_type; + union facility fac; + + enum facility_type out_fac_type; + union facility out_fac; enum event_e evq; @@ -226,14 +295,18 @@ struct misdn_bchannel { int active; int upset; - enum tone_e tone; + int generate_tone; int tone_cnt; - int tone_cnt2; - - enum bc_state_e state; + + enum bchannel_state bc_state; + enum bchannel_state next_bc_state; + int conf_id; + int holded; int stack_holder; + + struct misdn_bchannel *holded_bc; int pres; int screen; @@ -246,7 +319,7 @@ struct misdn_bchannel { int user1; int urate; - int async; + int hdlc; /* V110 */ unsigned char display[84]; @@ -254,16 +327,17 @@ struct misdn_bchannel { unsigned char oad[32]; unsigned char rad[32]; unsigned char dad[32]; + unsigned char cad[32]; unsigned char orig_dad[32]; unsigned char keypad[32]; - + unsigned char info_dad[64]; unsigned char infos_pending[64]; - unsigned char info_keypad[32]; - unsigned char clisub[24]; - unsigned char cldsub[24]; - unsigned char fac[132]; - unsigned char uu[256]; + +/* unsigned char info_keypad[32]; */ +/* unsigned char clisub[24]; */ +/* unsigned char cldsub[24]; */ +/* unsigned char uu[256]; */ int cause; int out_cause; @@ -276,6 +350,16 @@ struct misdn_bchannel { int ec_deftaps; int ec_whenbridged; int ec_training; + +#ifdef WITH_BEROEC + beroec_t *ec; + int bnec_tail; + int bnec_ah; + int bnec_nlp; + int bnec_td; + int bnec_adapt; + int bnec_zero; +#endif int orig; @@ -288,17 +372,19 @@ struct misdn_bchannel { enum event_response_e (*cb_event) (enum event_e event, struct misdn_bchannel *bc, void *user_data); void (*cb_log) (int level, int port, char *tmpl, ...); -int (*cb_clearl3_true)(void); +int (*cb_jb_empty)(struct misdn_bchannel *bc, char *buffer, int len); struct misdn_lib_iface { enum event_response_e (*cb_event)(enum event_e event, struct misdn_bchannel *bc, void *user_data); void (*cb_log)(int level, int port, char *tmpl, ...); - int (*cb_clearl3_true)(void); + int (*cb_jb_empty)(struct misdn_bchannel *bc, char *buffer, int len); }; /***** USER IFACE **********/ +void misdn_lib_nt_debug_init( int flags, char *file ); + int misdn_lib_init(char *portlist, struct misdn_lib_iface* iface, void *user_data); int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ); void misdn_lib_destroy(void); @@ -313,8 +399,8 @@ struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel); void manager_bchannel_activate(struct misdn_bchannel *bc); void manager_bchannel_deactivate(struct misdn_bchannel * bc); -int manager_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len); -void manager_send_tone (struct misdn_bchannel *bc, enum tone_e tone); + +int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len); void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2); @@ -322,7 +408,13 @@ void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2); int misdn_lib_port_restart(int port); int misdn_lib_get_port_info(int port); -int misdn_lib_port_up(int port); +int misdn_lib_is_port_blocked(int port); +int misdn_lib_port_block(int port); +int misdn_lib_port_unblock(int port); + +int misdn_lib_port_up(int port, int notcheck); + +int misdn_lib_get_port_down(int port); int misdn_lib_get_port_up (int port) ; @@ -339,24 +431,26 @@ int misdn_lib_send_facility(struct misdn_bchannel *bc, enum facility_type fac, v void manager_ec_enable(struct misdn_bchannel *bc); void manager_ec_disable(struct misdn_bchannel *bc); +void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone); + void get_show_stack_details(int port, char *buf); -/** Ibuf interface **/ -int misdn_ibuf_usedcount(void *buf); -int misdn_ibuf_freecount(void *buf); -void misdn_ibuf_memcpy_r(char *to, void *from, int len); -void misdn_ibuf_memcpy_w(void *buf, char *from, int len); +void misdn_lib_tone_generator_start(struct misdn_bchannel *bc); +void misdn_lib_tone_generator_stop(struct misdn_bchannel *bc); -/** Ibuf interface End **/ void misdn_lib_setup_bc(struct misdn_bchannel *bc); void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2); void misdn_lib_split_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2); +void misdn_lib_echo(struct misdn_bchannel *bc, int onoff); int misdn_lib_is_ptp(int port); +int misdn_lib_get_maxchans(int port); + +void misdn_lib_reinit_nt_stack(int port); #define PRI_TRANS_CAP_SPEECH 0x0 #define PRI_TRANS_CAP_DIGITAL 0x08 @@ -364,4 +458,11 @@ int misdn_lib_is_ptp(int port); #define PRI_TRANS_CAP_3_1K_AUDIO 0x10 #define PRI_TRANS_CAP_7K_AUDIO 0x11 + + +char *bc_state2str(enum bchannel_state state); +void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state); + + + #endif diff --git a/channels/misdn/isdn_lib_intern.h b/channels/misdn/isdn_lib_intern.h index 0305a2dad..ff63339bc 100644 --- a/channels/misdn/isdn_lib_intern.h +++ b/channels/misdn/isdn_lib_intern.h @@ -1,5 +1,5 @@ #ifndef ISDN_LIB_INTERN -#define ISDN_LIB_INTER +#define ISDN_LIB_INTERN #include <mISDNuser/mISDNlib.h> @@ -11,17 +11,13 @@ #include "isdn_lib.h" - - +#define QI_ELEMENT(a) a.off #ifndef mISDNUSER_HEAD_SIZE -#ifdef MISDNUSER_JOLLY #define mISDNUSER_HEAD_SIZE (sizeof(mISDNuser_head_t)) -#else -#define mISDNUSER_HEAD_SIZE (sizeof(mISDN_head_t)) -#endif +/*#define mISDNUSER_HEAD_SIZE (sizeof(mISDN_head_t))*/ #endif @@ -37,8 +33,6 @@ struct isdn_msg { void (*msg_parser)(struct isdn_msg *msgs, msg_t *msg, struct misdn_bchannel *bc, int nt); msg_t *(*msg_builder)(struct isdn_msg *msgs, struct misdn_bchannel *bc, int nt); - void (*msg_printer)(struct isdn_msg *msgs); - char *info; } ; @@ -60,9 +54,16 @@ struct misdn_stack { int b_stids[MAX_BCHANS + 1]; int ptp; + + int l2upcnt; + + int l2_id; int lower_id; int upper_id; + + int blocked; + int l2link; time_t l2establish; @@ -70,7 +71,7 @@ struct misdn_stack { int l1link; int midev; - enum mode_e {NT_MODE, TE_MODE} mode; + int nt; int pri; @@ -78,6 +79,7 @@ struct misdn_stack { int procids[0x100+1]; msg_queue_t downqueue; + msg_queue_t upqueue; int busy; int port; @@ -96,4 +98,6 @@ struct misdn_stack { struct misdn_stack* get_stack_by_bc(struct misdn_bchannel *bc); + + #endif diff --git a/channels/misdn/isdn_msg_parser.c b/channels/misdn/isdn_msg_parser.c index 9b59f8685..d23031ecb 100644 --- a/channels/misdn/isdn_msg_parser.c +++ b/channels/misdn/isdn_msg_parser.c @@ -12,30 +12,57 @@ */ +#include "isdn_lib_intern.h" + + #include "isdn_lib.h" + #include "ie.c" +#include "fac.h" + + +void set_channel(struct misdn_bchannel *bc, int channel) { + + cb_log(3,bc->port,"set_channel: bc->channel:%d channel:%d\n", bc->channel, channel); + + + if (channel==0xff) { + /* any channel */ + channel=-1; + } + + /* ALERT: is that everytime true ? */ + if (channel > 0 && bc->nt ) { + + if (bc->channel && ( bc->channel != 0xff) ) { + cb_log(0,bc->port,"We already have a channel (%d)\n", bc->channel); + } else { + bc->channel = channel; + } + } + + if (channel > 0 && !bc->nt ) + bc->channel = channel; +} void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; CALL_PROCEEDING_t *proceeding=(CALL_PROCEEDING_t*)((unsigned long)msg->data+ HEADER_LEN); - struct misdn_stack *stack=get_stack_by_bc(bc); + //struct misdn_stack *stack=get_stack_by_bc(bc); { int exclusive, channel; dec_ie_channel_id(proceeding->CHANNEL_ID, (Q931_info_t *)proceeding, &exclusive, &channel, nt,bc); + + set_channel(bc,channel); - if (channel==0xff) /* any channel */ - channel=-1; - - /* ALERT: is that everytime true ? */ - if (channel > 0 && stack->mode == NT_MODE) - bc->channel = channel; } dec_ie_progress(proceeding->PROGRESS, (Q931_info_t *)proceeding, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); + #if DEBUG printf("Parsing PROCEEDING Msg\n"); #endif @@ -59,9 +86,6 @@ msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *bc, int #endif return msg; } -void print_proceeding (struct isdn_msg msgs[]) -{ -} void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -94,9 +118,6 @@ msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt #endif return msg; } -void print_alerting (struct isdn_msg msgs[]) -{ -} void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) @@ -125,10 +146,6 @@ msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt #endif return msg; } -void print_progress (struct isdn_msg msgs[]) -{ -} - void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -142,87 +159,76 @@ void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, { int type,plan,present, screen; char id[32]; - dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, (unsigned char *)id, sizeof(id), nt,bc); + dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, (unsigned char *)id, sizeof(id)-1, nt,bc); bc->onumplan=type; strcpy(bc->oad, id); switch (present) { case 0: -// cb_log(3, bc->stack->port, " --> Pres:0\n"); bc->pres=0; /* screened */ break; case 1: -// cb_log(3, bc->stack->port, " --> Pres:1\n"); bc->pres=1; /* not screened */ break; default: -// cb_log(3, bc->stack->port, " --> Pres:%d\n",present); bc->pres=0; } switch (screen) { case 0: -// cb_log(4, bc->stack->port, " --> Screen:0\n"); break; default: -// cb_log(4, bc->stack->port, " --> Screen:%d\n",screen); ; } } { int type, plan; char number[32]; - dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)setup, &type, &plan, (unsigned char *)number, sizeof(number), nt,bc); + dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)setup, &type, &plan, (unsigned char *)number, sizeof(number)-1, nt,bc); strcpy(bc->dad, number); bc->dnumplan=type; } { char keypad[32]; - dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)setup, (unsigned char *)keypad, sizeof(keypad), nt,bc); + dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)setup, (unsigned char *)keypad, sizeof(keypad)-1, nt,bc); strcpy(bc->keypad, keypad); } { - int sending_complete; - dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &sending_complete, nt,bc); + dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &bc->sending_complete, nt,bc); + } { int type, plan, present, screen, reason; char id[32]; - dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *)setup, &type, &plan, &present, &screen, &reason, (unsigned char *)id, sizeof(id), nt,bc); + dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *)setup, &type, &plan, &present, &screen, &reason, (unsigned char *)id, sizeof(id)-1, nt,bc); strcpy(bc->rad, id); bc->rnumplan=type; -// cb_log(3, bc->stack->port, " --> Redirecting number (REDIR_NR): '%s'\n", id); } { int coding, capability, mode, rate, multi, user, async, urate, stopbits, dbits, parity; dec_ie_bearer(setup->BEARER, (Q931_info_t *)setup, &coding, &capability, &mode, &rate, &multi, &user, &async, &urate, &stopbits, &dbits, &parity, nt,bc); switch (capability) { case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED; -// cb_log(2, bc->stack->port, " --> cap -1 -> digital\n"); break; case 0: bc->capability=INFO_CAPABILITY_SPEECH; -// cb_log(2, bc->stack->port, " --> cap speech\n"); + break; + case 18: bc->capability=INFO_CAPABILITY_VIDEO; break; case 8: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED; bc->user1 = user; - bc->async = async; bc->urate = urate; bc->rate = rate; bc->mode = mode; - -// cb_log(2, bc->stack->port, " --> cap unres Digital (user l1 %d, async %d, user rate %d\n", user, async, urate); break; case 9: bc->capability=INFO_CAPABILITY_DIGITAL_RESTRICTED; -// cb_log(2, bc->stack->port, " --> cap res Digital\n"); break; default: -// cb_log(2, bc->stack->port, " --> cap Else\n"); break; } - + switch(user) { case 2: bc->law=INFO_CODEC_ULAW; @@ -240,11 +246,8 @@ void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, { int exclusive, channel; dec_ie_channel_id(setup->CHANNEL_ID, (Q931_info_t *)setup, &exclusive, &channel, nt,bc); - if (channel==0xff) /* any channel */ - channel=-1; - - if (channel > 0) - bc->channel = channel; + + set_channel(bc,channel); } dec_ie_progress(setup->PROGRESS, (Q931_info_t *)setup, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); @@ -260,12 +263,12 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) setup=(SETUP_t*)((msg->data+HEADER_LEN)); -// cb_log(2, bc->stack->port, " --> oad %s dad %s channel %d\n",bc->oad, bc->dad,bc->channel); if (bc->channel == 0 || bc->channel == ANY_CHANNEL || bc->channel==-1) enc_ie_channel_id(&setup->CHANNEL_ID, msg, 0, bc->channel, nt,bc); - else + else enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc); - + + { int type=bc->onumplan,plan=1,present=bc->pres,screen=bc->screen; enc_ie_calling_pn(&setup->CALLING_PN, msg, type, plan, present, @@ -276,6 +279,13 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) if (bc->dad[0]) enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dnumplan, 1, bc->dad, nt,bc); } + + { + if (bc->rad[0]) + enc_ie_redir_nr(&setup->REDIR_NR, msg, 1, 1, bc->pres, bc->screen, 0, bc->rad, nt,bc); + } + + if (*bc->display) { enc_ie_display(&setup->DISPLAY, msg, bc->display, nt,bc); @@ -299,6 +309,8 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) break; case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: capability = 8; user=-1; + mode=bc->mode; + rate=bc->rate; break; case INFO_CAPABILITY_DIGITAL_RESTRICTED: capability = 9; user=-1; @@ -318,19 +330,23 @@ msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) return msg; } -void print_setup (struct isdn_msg msgs[]) -{ -} - void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; CONNECT_t *connect=(CONNECT_t*)((unsigned long)(msg->data+HEADER_LEN)); + int plan,pres,screen; + bc->ces = connect->ces; bc->ces = connect->ces; dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); + + dec_ie_connected_pn(connect->CONNECT_PN,(Q931_info_t *)connect, &bc->cpnnumplan, &plan, &pres, &screen, bc->cad, 31, nt, bc); + + /* + cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type); + */ #if DEBUG printf("Parsing CONNECT Msg\n"); @@ -341,7 +357,9 @@ msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; CONNECT_t *connect; msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt); - + + cb_log(6,bc->port,"BUILD_CONNECT: bc:%p bc->l3id:%d, nt:%d\n",bc,bc->l3_id,nt); + connect=(CONNECT_t*)((msg->data+HEADER_LEN)); if (nt) { @@ -351,8 +369,8 @@ msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) } { - int type=0, plan=1, present=2, screen=0; - enc_ie_connected_pn(&connect->CONNECT_PN, msg, type,plan, present, screen, (unsigned char*) bc->dad , nt , bc); + int type=bc->cpnnumplan, plan=1, present=2, screen=0; + enc_ie_connected_pn(&connect->CONNECT_PN, msg, type,plan, present, screen, (unsigned char*) bc->cad, nt , bc); } #if DEBUG @@ -360,10 +378,6 @@ msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) #endif return msg; } -void print_connect (struct isdn_msg msgs[]) -{ -} - void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -374,11 +388,8 @@ void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_b int exclusive, channel; dec_ie_channel_id(setup_acknowledge->CHANNEL_ID, (Q931_info_t *)setup_acknowledge, &exclusive, &channel, nt,bc); - if (channel==0xff) /* any channel */ - channel=-1; - if (channel > 0) - bc->channel = channel; + set_channel(bc, channel); } dec_ie_progress(setup_acknowledge->PROGRESS, (Q931_info_t *)setup_acknowledge, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); @@ -407,10 +418,6 @@ msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *b return msg; } -void print_setup_acknowledge (struct isdn_msg msgs[]) -{ -} - void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { #if DEBUG @@ -434,10 +441,6 @@ msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel #endif return msg; } -void print_connect_acknowledge (struct isdn_msg msgs[]) -{ -} - void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -460,10 +463,6 @@ msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc #endif return msg; } -void print_user_information (struct isdn_msg msgs[]) -{ -} - void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -486,10 +485,6 @@ msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, #endif return msg; } -void print_suspend_reject (struct isdn_msg msgs[]) -{ -} - void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -512,10 +507,6 @@ msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, i #endif return msg; } -void print_resume_reject (struct isdn_msg msgs[]) -{ -} - void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -538,10 +529,6 @@ msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) #endif return msg; } -void print_hold (struct isdn_msg msgs[]) -{ -} - void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -564,10 +551,6 @@ msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) #endif return msg; } -void print_suspend (struct isdn_msg msgs[]) -{ -} - void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -590,10 +573,6 @@ msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) #endif return msg; } -void print_resume (struct isdn_msg msgs[]) -{ -} - void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -616,10 +595,6 @@ msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc #endif return msg; } -void print_hold_acknowledge (struct isdn_msg msgs[]) -{ -} - void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -642,10 +617,6 @@ msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel #endif return msg; } -void print_suspend_acknowledge (struct isdn_msg msgs[]) -{ -} - void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -668,10 +639,6 @@ msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel * #endif return msg; } -void print_resume_acknowledge (struct isdn_msg msgs[]) -{ -} - void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -694,10 +661,6 @@ msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int #endif return msg; } -void print_hold_reject (struct isdn_msg msgs[]) -{ -} - void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -720,10 +683,6 @@ msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt #endif return msg; } -void print_retrieve (struct isdn_msg msgs[]) -{ -} - void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -747,10 +706,6 @@ msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel #endif return msg; } -void print_retrieve_acknowledge (struct isdn_msg msgs[]) -{ -} - void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -773,10 +728,6 @@ msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, #endif return msg; } -void print_retrieve_reject (struct isdn_msg msgs[]) -{ -} - void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -809,10 +760,6 @@ msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int #endif return msg; } -void print_disconnect (struct isdn_msg msgs[]) -{ -} - void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -827,10 +774,10 @@ void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *b { int exclusive, channel; - dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &channel, nt,bc); + dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &bc->restart_channel, nt,bc); if (channel==0xff) /* any channel */ channel=-1; - cb_log(0, stack->port, "CC_RESTART Request on channel:%d on port:%d\n",stack->port); + cb_log(3, stack->port, "CC_RESTART Request on channel:%d on this port.\n"); } @@ -848,10 +795,6 @@ msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) #endif return msg; } -void print_restart (struct isdn_msg msgs[]) -{ -} - void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -874,18 +817,14 @@ msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) release=(RELEASE_t*)((msg->data+HEADER_LEN)); - - enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc); + if (bc->out_cause>= 0) + enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc); #if DEBUG printf("Building RELEASE Msg\n"); #endif return msg; } -void print_release (struct isdn_msg msgs[]) -{ -} - void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -895,35 +834,30 @@ void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bc iframe_t *frm = (iframe_t*) msg->data; struct misdn_stack *stack=get_stack_by_bc(bc); - -#ifdef MISDNUSER_JOLLY mISDNuser_head_t *hh; hh=(mISDNuser_head_t*)msg->data; -#else - mISDN_head_t *hh; - hh=(mISDN_head_t*)msg->data; -#endif - + + /*hh=(mISDN_head_t*)msg->data; + mISDN_head_t *hh;*/ + if (nt) { if (hh->prim == (CC_RELEASE_COMPLETE|CONFIRM)) { - cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [NT] port:%d\n",stack->port); + cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [NT] \n"); return; } } else { if (frm->prim == (CC_RELEASE_COMPLETE|CONFIRM)) { - cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [TE] port:%d\n",stack->port); + cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [TE] \n"); return; } } dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)(release_complete), &location, &bc->cause, nt,bc); - #if DEBUG printf("Parsing RELEASE_COMPLETE Msg\n"); #endif - - } + msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; @@ -939,31 +873,26 @@ msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc #endif return msg; } -void print_release_complete (struct isdn_msg msgs[]) -{ -} - void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { +//#define FACILITY_DECODE +#ifdef FACILITY_DECODE int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; FACILITY_t *facility=(FACILITY_t*)((unsigned long)(msg->data+HEADER_LEN)); Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN); - #if DEBUG printf("Parsing FACILITY Msg\n"); #endif { - char fac[128]; - int facility_len; - - dec_ie_facility(facility->FACILITY, qi, fac, &facility_len, nt, bc); + fac_dec(facility->FACILITY, qi, &bc->fac_type, &bc->fac, bc); } - - +#endif + } + msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; @@ -977,17 +906,9 @@ msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt printf("Sending %s as Display\n", bc->display); enc_ie_display(&facility->DISPLAY, msg, bc->display, nt,bc); } - - switch ( bc->facility ) { - case FACILITY_CALLDEFLECT: - enc_facility_calldeflect(&facility->FACILITY, msg, bc->facility_calldeflect_nr, nt, bc); - - break; - case FACILITY_NONE: - break; - } + fac_enc(&facility->FACILITY, msg, bc->out_fac_type, bc->out_fac, bc); } @@ -996,19 +917,14 @@ msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt #endif return msg; } -void print_facility (struct isdn_msg msgs[]) -{ -} - void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { #if DEBUG printf("Parsing NOTIFY Msg\n"); #endif - - } + msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; @@ -1022,19 +938,14 @@ msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) #endif return msg; } -void print_notify (struct isdn_msg msgs[]) -{ -} - void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { #if DEBUG printf("Parsing STATUS_ENQUIRY Msg\n"); #endif - - } + msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; @@ -1048,32 +959,25 @@ msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, #endif return msg; } -void print_status_enquiry (struct isdn_msg msgs[]) -{ -} - void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; INFORMATION_t *information=(INFORMATION_t*)((unsigned long)(msg->data+HEADER_LEN)); - { int type, plan; char number[32]; char keypad[32]; - dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *)information, &type, &plan, (unsigned char *)number, sizeof(number), nt,bc); - dec_ie_keypad(information->KEYPAD, (Q931_info_t *)information, (unsigned char *)keypad, sizeof(keypad), nt,bc); + dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *)information, &type, &plan, (unsigned char *)number, sizeof(number)-1, nt, bc); + dec_ie_keypad(information->KEYPAD, (Q931_info_t *)information, (unsigned char *)keypad, sizeof(keypad)-1, nt, bc); strcpy(bc->info_dad, number); strcpy(bc->keypad,keypad); - } #if DEBUG printf("Parsing INFORMATION Msg\n"); #endif - - } + msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; @@ -1098,10 +1002,6 @@ msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int #endif return msg; } -void print_information (struct isdn_msg msgs[]) -{ -} - void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { @@ -1115,9 +1015,8 @@ void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc #if DEBUG printf("Parsing STATUS Msg\n"); #endif - - } + msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; @@ -1131,19 +1030,14 @@ msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) #endif return msg; } -void print_status (struct isdn_msg msgs[]) -{ -} - void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { #if DEBUG printf("Parsing STATUS Msg\n"); -#endif - - +#endif } + msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; @@ -1157,9 +1051,6 @@ msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) #endif return msg; } -void print_timeout (struct isdn_msg msgs[]) -{ -} /************************************/ @@ -1171,96 +1062,96 @@ void print_timeout (struct isdn_msg msgs[]) struct isdn_msg msgs_g[] = { {CC_PROCEEDING,L3,EVENT_PROCEEDING, - parse_proceeding,build_proceeding,print_proceeding, + parse_proceeding,build_proceeding, "PROCEEDING"}, {CC_ALERTING,L3,EVENT_ALERTING, - parse_alerting,build_alerting,print_alerting, + parse_alerting,build_alerting, "ALERTING"}, {CC_PROGRESS,L3,EVENT_PROGRESS, - parse_progress,build_progress,print_progress, + parse_progress,build_progress, "PROGRESS"}, {CC_SETUP,L3,EVENT_SETUP, - parse_setup,build_setup,print_setup, + parse_setup,build_setup, "SETUP"}, {CC_CONNECT,L3,EVENT_CONNECT, - parse_connect,build_connect,print_connect, + parse_connect,build_connect, "CONNECT"}, {CC_SETUP_ACKNOWLEDGE,L3,EVENT_SETUP_ACKNOWLEDGE, - parse_setup_acknowledge,build_setup_acknowledge,print_setup_acknowledge, + parse_setup_acknowledge,build_setup_acknowledge, "SETUP_ACKNOWLEDGE"}, {CC_CONNECT_ACKNOWLEDGE ,L3,EVENT_CONNECT_ACKNOWLEDGE , - parse_connect_acknowledge ,build_connect_acknowledge ,print_connect_acknowledge , + parse_connect_acknowledge ,build_connect_acknowledge, "CONNECT_ACKNOWLEDGE "}, {CC_USER_INFORMATION,L3,EVENT_USER_INFORMATION, - parse_user_information,build_user_information,print_user_information, + parse_user_information,build_user_information, "USER_INFORMATION"}, {CC_SUSPEND_REJECT,L3,EVENT_SUSPEND_REJECT, - parse_suspend_reject,build_suspend_reject,print_suspend_reject, + parse_suspend_reject,build_suspend_reject, "SUSPEND_REJECT"}, {CC_RESUME_REJECT,L3,EVENT_RESUME_REJECT, - parse_resume_reject,build_resume_reject,print_resume_reject, + parse_resume_reject,build_resume_reject, "RESUME_REJECT"}, {CC_HOLD,L3,EVENT_HOLD, - parse_hold,build_hold,print_hold, + parse_hold,build_hold, "HOLD"}, {CC_SUSPEND,L3,EVENT_SUSPEND, - parse_suspend,build_suspend,print_suspend, + parse_suspend,build_suspend, "SUSPEND"}, {CC_RESUME,L3,EVENT_RESUME, - parse_resume,build_resume,print_resume, + parse_resume,build_resume, "RESUME"}, {CC_HOLD_ACKNOWLEDGE,L3,EVENT_HOLD_ACKNOWLEDGE, - parse_hold_acknowledge,build_hold_acknowledge,print_hold_acknowledge, + parse_hold_acknowledge,build_hold_acknowledge, "HOLD_ACKNOWLEDGE"}, {CC_SUSPEND_ACKNOWLEDGE,L3,EVENT_SUSPEND_ACKNOWLEDGE, - parse_suspend_acknowledge,build_suspend_acknowledge,print_suspend_acknowledge, + parse_suspend_acknowledge,build_suspend_acknowledge, "SUSPEND_ACKNOWLEDGE"}, {CC_RESUME_ACKNOWLEDGE,L3,EVENT_RESUME_ACKNOWLEDGE, - parse_resume_acknowledge,build_resume_acknowledge,print_resume_acknowledge, + parse_resume_acknowledge,build_resume_acknowledge, "RESUME_ACKNOWLEDGE"}, {CC_HOLD_REJECT,L3,EVENT_HOLD_REJECT, - parse_hold_reject,build_hold_reject,print_hold_reject, + parse_hold_reject,build_hold_reject, "HOLD_REJECT"}, {CC_RETRIEVE,L3,EVENT_RETRIEVE, - parse_retrieve,build_retrieve,print_retrieve, + parse_retrieve,build_retrieve, "RETRIEVE"}, {CC_RETRIEVE_ACKNOWLEDGE,L3,EVENT_RETRIEVE_ACKNOWLEDGE, - parse_retrieve_acknowledge,build_retrieve_acknowledge,print_retrieve_acknowledge, + parse_retrieve_acknowledge,build_retrieve_acknowledge, "RETRIEVE_ACKNOWLEDGE"}, {CC_RETRIEVE_REJECT,L3,EVENT_RETRIEVE_REJECT, - parse_retrieve_reject,build_retrieve_reject,print_retrieve_reject, + parse_retrieve_reject,build_retrieve_reject, "RETRIEVE_REJECT"}, {CC_DISCONNECT,L3,EVENT_DISCONNECT, - parse_disconnect,build_disconnect,print_disconnect, + parse_disconnect,build_disconnect, "DISCONNECT"}, {CC_RESTART,L3,EVENT_RESTART, - parse_restart,build_restart,print_restart, + parse_restart,build_restart, "RESTART"}, {CC_RELEASE,L3,EVENT_RELEASE, - parse_release,build_release,print_release, + parse_release,build_release, "RELEASE"}, {CC_RELEASE_COMPLETE,L3,EVENT_RELEASE_COMPLETE, - parse_release_complete,build_release_complete,print_release_complete, + parse_release_complete,build_release_complete, "RELEASE_COMPLETE"}, {CC_FACILITY,L3,EVENT_FACILITY, - parse_facility,build_facility,print_facility, + parse_facility,build_facility, "FACILITY"}, {CC_NOTIFY,L3,EVENT_NOTIFY, - parse_notify,build_notify,print_notify, + parse_notify,build_notify, "NOTIFY"}, {CC_STATUS_ENQUIRY,L3,EVENT_STATUS_ENQUIRY, - parse_status_enquiry,build_status_enquiry,print_status_enquiry, + parse_status_enquiry,build_status_enquiry, "STATUS_ENQUIRY"}, {CC_INFORMATION,L3,EVENT_INFORMATION, - parse_information,build_information,print_information, + parse_information,build_information, "INFORMATION"}, {CC_STATUS,L3,EVENT_STATUS, - parse_status,build_status,print_status, + parse_status,build_status, "STATUS"}, {CC_TIMEOUT,L3,EVENT_TIMEOUT, - parse_timeout,build_timeout,print_timeout, + parse_timeout,build_timeout, "TIMEOUT"}, - {0,0,0,NULL,NULL,NULL,NULL} + {0,0,0,NULL,NULL,NULL} }; #define msgs_max (sizeof(msgs_g)/sizeof(struct isdn_msg)) @@ -1271,15 +1162,12 @@ int isdn_msg_get_index(struct isdn_msg msgs[], msg_t *msg, int nt) int i; if (nt){ -#ifdef MISDNUSER_JOLLY mISDNuser_head_t *hh = (mISDNuser_head_t*)msg->data; -#else - mISDN_head_t *hh = (mISDN_head_t*)msg->data; -#endif - - for (i=0; i< msgs_max -1; i++) + + for (i=0; i< msgs_max -1; i++) { if ( (hh->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i; - + } + } else { iframe_t *frm = (iframe_t*)msg->data; @@ -1296,7 +1184,7 @@ int isdn_msg_get_index_by_event(struct isdn_msg msgs[], enum event_e event, int for (i=0; i< msgs_max; i++) if ( event == msgs[i].event) return i; - cb_log(4,0, "get_index: EVENT NOT FOUND!!\n"); + cb_log(10,0, "get_index: event not found!\n"); return -1; } @@ -1320,7 +1208,10 @@ char EVENT_CLEAN_INFO[] = "CLEAN_UP"; char EVENT_DTMF_TONE_INFO[] = "DTMF_TONE"; char EVENT_NEW_L3ID_INFO[] = "NEW_L3ID"; char EVENT_NEW_BC_INFO[] = "NEW_BC"; +char EVENT_PORT_ALARM_INFO[] = "ALARM"; char EVENT_BCHAN_DATA_INFO[] = "BCHAN_DATA"; +char EVENT_BCHAN_ACTIVATED_INFO[] = "BCHAN_ACTIVATED"; +char EVENT_TONE_GENERATE_INFO[] = "TONE_GENERATE"; char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt) { @@ -1333,6 +1224,9 @@ char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt) if (event == EVENT_NEW_L3ID) return EVENT_NEW_L3ID_INFO; if (event == EVENT_NEW_BC) return EVENT_NEW_BC_INFO; if (event == EVENT_BCHAN_DATA) return EVENT_BCHAN_DATA_INFO; + if (event == EVENT_BCHAN_ACTIVATED) return EVENT_BCHAN_ACTIVATED_INFO; + if (event == EVENT_TONE_GENERATE) return EVENT_TONE_GENERATE_INFO; + if (event == EVENT_PORT_ALARM) return EVENT_PORT_ALARM_INFO; return NULL; } diff --git a/channels/misdn/mISDN.patch b/channels/misdn/mISDN.patch deleted file mode 100644 index ccc8ae4b2..000000000 --- a/channels/misdn/mISDN.patch +++ /dev/null @@ -1,2500 +0,0 @@ -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/arith.h mISDN/drivers/isdn/hardware/mISDN/arith.h ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/arith.h 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/arith.h 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,347 @@ -+#ifndef _ZAPTEL_ARITH_H -+#define _ZAPTEL_ARITH_H -+/* -+ * Handy add/subtract functions to operate on chunks of shorts. -+ * Feel free to add customizations for additional architectures -+ * -+ */ -+ -+#ifdef CONFIG_ZAPTEL_MMX -+#ifdef ZT_CHUNKSIZE -+static inline void __ACSS(volatile short *dst, const short *src) -+{ -+ __asm__ __volatile__ ( -+ "movq 0(%0), %%mm0;\n" -+ "movq 0(%1), %%mm1;\n" -+ "movq 8(%0), %%mm2;\n" -+ "movq 8(%1), %%mm3;\n" -+ "paddsw %%mm1, %%mm0;\n" -+ "paddsw %%mm3, %%mm2;\n" -+ "movq %%mm0, 0(%0);\n" -+ "movq %%mm2, 8(%0);\n" -+ : "=r" (dst) -+ : "r" (src), "0" (dst) -+ : "memory" -+#if CLOBBERMMX -+ , "%mm0", "%mm1", "%mm2", "%mm3" -+#endif -+ ); -+ -+} -+static inline void __SCSS(volatile short *dst, const short *src) -+{ -+ __asm__ __volatile__ ( -+ "movq 0(%0), %%mm0;\n" -+ "movq 0(%1), %%mm1;\n" -+ "movq 8(%0), %%mm2;\n" -+ "movq 8(%1), %%mm3;\n" -+ "psubsw %%mm1, %%mm0;\n" -+ "psubsw %%mm3, %%mm2;\n" -+ "movq %%mm0, 0(%0);\n" -+ "movq %%mm2, 8(%0);\n" -+ : "=r" (dst) -+ : "r" (src), "0" (dst) -+ : "memory" -+#if CLOBBERMMX -+ , "%mm0", "%mm1", "%mm2", "%mm3" -+#endif -+ ); -+ -+} -+ -+#if (ZT_CHUNKSIZE == 8) -+#define ACSS(a,b) __ACSS(a,b) -+#define SCSS(a,b) __SCSS(a,b) -+#elif (ZT_CHUNKSIZE > 8) -+static inline void ACSS(volatile short *dst, const short *src) -+{ -+ int x; -+ for (x=0;x<ZT_CHUNKSIZE;x+=8) -+ __ACSS(dst + x, src + x); -+} -+static inline void SCSS(volatile short *dst, const short *src) -+{ -+ int x; -+ for (x=0;x<ZT_CHUNKSIZE;x+=8) -+ __SCSS(dst + x, src + x); -+} -+#else -+#error No MMX for ZT_CHUNKSIZE < 8 -+#endif -+#endif -+static inline int CONVOLVE(const int *coeffs, const short *hist, int len) -+{ -+ int sum; -+ /* Divide length by 16 */ -+ len >>= 4; -+ -+ /* Clear our accumulator, mm4 */ -+ -+ /* -+ -+ For every set of eight... -+ -+ Load 16 coefficients into four registers... -+ Shift each word right 16 to make them shorts... -+ Pack the resulting shorts into two registers... -+ With the coefficients now in mm0 and mm2, load the -+ history into mm1 and mm3... -+ Multiply/add mm1 into mm0, and mm3 into mm2... -+ Add mm2 into mm0 (without saturation, alas). Now we have two half-results. -+ Accumulate in mm4 (again, without saturation, alas) -+ */ -+ __asm__ ( -+ "pxor %%mm4, %%mm4;\n" -+ "mov %1, %%edi;\n" -+ "mov %2, %%esi;\n" -+ "mov %3, %%ecx;\n" -+ "1:" -+ "movq 0(%%edi), %%mm0;\n" -+ "movq 8(%%edi), %%mm1;\n" -+ "movq 16(%%edi), %%mm2;\n" -+ "movq 24(%%edi), %%mm3;\n" -+ /* can't use 4/5 since 4 is the accumulator for us */ -+ "movq 32(%%edi), %%mm6;\n" -+ "movq 40(%%edi), %%mm7;\n" -+ "psrad $16, %%mm0;\n" -+ "psrad $16, %%mm1;\n" -+ "psrad $16, %%mm2;\n" -+ "psrad $16, %%mm3;\n" -+ "psrad $16, %%mm6;\n" -+ "psrad $16, %%mm7;\n" -+ "packssdw %%mm1, %%mm0;\n" -+ "packssdw %%mm3, %%mm2;\n" -+ "packssdw %%mm7, %%mm6;\n" -+ "movq 0(%%esi), %%mm1;\n" -+ "movq 8(%%esi), %%mm3;\n" -+ "movq 16(%%esi), %%mm7;\n" -+ "pmaddwd %%mm1, %%mm0;\n" -+ "pmaddwd %%mm3, %%mm2;\n" -+ "pmaddwd %%mm7, %%mm6;\n" -+ "paddd %%mm6, %%mm4;\n" -+ "paddd %%mm2, %%mm4;\n" -+ "paddd %%mm0, %%mm4;\n" -+ /* Come back and do for the last few bytes */ -+ "movq 48(%%edi), %%mm6;\n" -+ "movq 56(%%edi), %%mm7;\n" -+ "psrad $16, %%mm6;\n" -+ "psrad $16, %%mm7;\n" -+ "packssdw %%mm7, %%mm6;\n" -+ "movq 24(%%esi), %%mm7;\n" -+ "pmaddwd %%mm7, %%mm6;\n" -+ "paddd %%mm6, %%mm4;\n" -+ "add $64, %%edi;\n" -+ "add $32, %%esi;\n" -+ "dec %%ecx;\n" -+ "jnz 1b;\n" -+ "movq %%mm4, %%mm0;\n" -+ "psrlq $32, %%mm0;\n" -+ "paddd %%mm0, %%mm4;\n" -+ "movd %%mm4, %0;\n" -+ : "=r" (sum) -+ : "r" (coeffs), "r" (hist), "r" (len) -+ : "%ecx", "%edi", "%esi" -+ ); -+ -+ return sum; -+} -+ -+static inline void UPDATE(volatile int *taps, const short *history, const int nsuppr, const int ntaps) -+{ -+ int i; -+ int correction; -+ for (i=0;i<ntaps;i++) { -+ correction = history[i] * nsuppr; -+ taps[i] += correction; -+ } -+} -+ -+static inline void UPDATE2(volatile int *taps, volatile short *taps_short, const short *history, const int nsuppr, const int ntaps) -+{ -+ int i; -+ int correction; -+#if 0 -+ ntaps >>= 4; -+ /* First, load up taps, */ -+ __asm__ ( -+ "pxor %%mm4, %%mm4;\n" -+ "mov %0, %%edi;\n" -+ "mov %1, %%esi;\n" -+ "mov %3, %%ecx;\n" -+ "1:" -+ "jnz 1b;\n" -+ "movq %%mm4, %%mm0;\n" -+ "psrlq $32, %%mm0;\n" -+ "paddd %%mm0, %%mm4;\n" -+ "movd %%mm4, %0;\n" -+ : "=r" (taps), "=r" (taps_short) -+ : "r" (history), "r" (nsuppr), "r" (ntaps), "0" (taps) -+ : "%ecx", "%edi", "%esi" -+ ); -+#endif -+#if 1 -+ for (i=0;i<ntaps;i++) { -+ correction = history[i] * nsuppr; -+ taps[i] += correction; -+ taps_short[i] = taps[i] >> 16; -+ } -+#endif -+} -+ -+static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) -+{ -+ int sum; -+ /* Divide length by 16 */ -+ len >>= 4; -+ -+ /* Clear our accumulator, mm4 */ -+ -+ /* -+ -+ For every set of eight... -+ Load in eight coefficients and eight historic samples, multliply add and -+ accumulate the result -+ */ -+ __asm__ ( -+ "pxor %%mm4, %%mm4;\n" -+ "mov %1, %%edi;\n" -+ "mov %2, %%esi;\n" -+ "mov %3, %%ecx;\n" -+ "1:" -+ "movq 0(%%edi), %%mm0;\n" -+ "movq 8(%%edi), %%mm2;\n" -+ "movq 0(%%esi), %%mm1;\n" -+ "movq 8(%%esi), %%mm3;\n" -+ "pmaddwd %%mm1, %%mm0;\n" -+ "pmaddwd %%mm3, %%mm2;\n" -+ "paddd %%mm2, %%mm4;\n" -+ "paddd %%mm0, %%mm4;\n" -+ "movq 16(%%edi), %%mm0;\n" -+ "movq 24(%%edi), %%mm2;\n" -+ "movq 16(%%esi), %%mm1;\n" -+ "movq 24(%%esi), %%mm3;\n" -+ "pmaddwd %%mm1, %%mm0;\n" -+ "pmaddwd %%mm3, %%mm2;\n" -+ "paddd %%mm2, %%mm4;\n" -+ "paddd %%mm0, %%mm4;\n" -+ "add $32, %%edi;\n" -+ "add $32, %%esi;\n" -+ "dec %%ecx;\n" -+ "jnz 1b;\n" -+ "movq %%mm4, %%mm0;\n" -+ "psrlq $32, %%mm0;\n" -+ "paddd %%mm0, %%mm4;\n" -+ "movd %%mm4, %0;\n" -+ : "=r" (sum) -+ : "r" (coeffs), "r" (hist), "r" (len) -+ : "%ecx", "%edi", "%esi" -+ ); -+ -+ return sum; -+} -+static inline short MAX16(const short *y, int len, int *pos) -+{ -+ int k; -+ short max = 0; -+ int bestpos = 0; -+ for (k=0;k<len;k++) { -+ if (max < y[k]) { -+ bestpos = k; -+ max = y[k]; -+ } -+ } -+ *pos = (len - 1 - bestpos); -+ return max; -+} -+ -+ -+ -+#else -+ -+#ifdef ZT_CHUNKSIZE -+static inline void ACSS(short *dst, short *src) -+{ -+ int x,sum; -+ /* Add src to dst with saturation, storing in dst */ -+ for (x=0;x<ZT_CHUNKSIZE;x++) { -+ sum = dst[x]+src[x]; -+ if (sum > 32767) -+ sum = 32767; -+ else if (sum < -32768) -+ sum = -32768; -+ dst[x] = sum; -+ } -+} -+ -+static inline void SCSS(short *dst, short *src) -+{ -+ int x,sum; -+ /* Add src to dst with saturation, storing in dst */ -+ for (x=0;x<ZT_CHUNKSIZE;x++) { -+ sum = dst[x]-src[x]; -+ if (sum > 32767) -+ sum = 32767; -+ else if (sum < -32768) -+ sum = -32768; -+ dst[x] = sum; -+ } -+} -+ -+#endif /* ZT_CHUNKSIZE */ -+ -+static inline int CONVOLVE(const int *coeffs, const short *hist, int len) -+{ -+ int x; -+ int sum = 0; -+ for (x=0;x<len;x++) -+ sum += (coeffs[x] >> 16) * hist[x]; -+ return sum; -+} -+ -+static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) -+{ -+ int x; -+ int sum = 0; -+ for (x=0;x<len;x++) -+ sum += coeffs[x] * hist[x]; -+ return sum; -+} -+ -+static inline void UPDATE(int *taps, const short *history, const int nsuppr, const int ntaps) -+{ -+ int i; -+ int correction; -+ for (i=0;i<ntaps;i++) { -+ correction = history[i] * nsuppr; -+ taps[i] += correction; -+ } -+} -+ -+static inline void UPDATE2(int *taps, short *taps_short, const short *history, const int nsuppr, const int ntaps) -+{ -+ int i; -+ int correction; -+ for (i=0;i<ntaps;i++) { -+ correction = history[i] * nsuppr; -+ taps[i] += correction; -+ taps_short[i] = taps[i] >> 16; -+ } -+} -+ -+static inline short MAX16(const short *y, int len, int *pos) -+{ -+ int k; -+ short max = 0; -+ int bestpos = 0; -+ for (k=0;k<len;k++) { -+ if (max < y[k]) { -+ bestpos = k; -+ max = y[k]; -+ } -+ } -+ *pos = (len - 1 - bestpos); -+ return max; -+} -+ -+#endif /* MMX */ -+#endif /* _ZAPTEL_ARITH_H */ -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/biquad.h mISDN/drivers/isdn/hardware/mISDN/biquad.h ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/biquad.h 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/biquad.h 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,73 @@ -+/* -+ * SpanDSP - a series of DSP components for telephony -+ * -+ * biquad.h - General telephony bi-quad section routines (currently this just -+ * handles canonic/type 2 form) -+ * -+ * Written by Steve Underwood <steveu@coppice.org> -+ * -+ * Copyright (C) 2001 Steve Underwood -+ * -+ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ */ -+ -+typedef struct -+{ -+ int32_t gain; -+ int32_t a1; -+ int32_t a2; -+ int32_t b1; -+ int32_t b2; -+ -+ int32_t z1; -+ int32_t z2; -+} biquad2_state_t; -+ -+static inline void biquad2_init (biquad2_state_t *bq, -+ int32_t gain, -+ int32_t a1, -+ int32_t a2, -+ int32_t b1, -+ int32_t b2) -+{ -+ bq->gain = gain; -+ bq->a1 = a1; -+ bq->a2 = a2; -+ bq->b1 = b1; -+ bq->b2 = b2; -+ -+ bq->z1 = 0; -+ bq->z2 = 0; -+} -+/*- End of function --------------------------------------------------------*/ -+ -+static inline int16_t biquad2 (biquad2_state_t *bq, int16_t sample) -+{ -+ int32_t y; -+ int32_t z0; -+ -+ z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2; -+ y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2; -+ -+ bq->z2 = bq->z1; -+ bq->z1 = z0 >> 15; -+ y >>= 15; -+ return y; -+} -+/*- End of function --------------------------------------------------------*/ -+/*- End of file ------------------------------------------------------------*/ -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,390 @@ -+/* $Id$ -+ * -+ * Simple but fast Echo cancellation for mISDN_dsp. -+ * -+ * Copyright Andreas Eversberg (jolly@jolly.de) -+ * -+ * This software may be used and distributed according to the terms -+ * of the GNU General Public License, incorporated herein by reference. -+ * -+ */ -+ -+#include "layer1.h" -+#include "helper.h" -+#include "debug.h" -+#include "dsp.h" -+ -+ -+/* -+ * how this works: -+ * -+ * -+ * -+ */ -+void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size); -+int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int train); -+void bchdev_echocancel_deactivate(dsp_t* dev); -+ -+ -+ -+ -+ -+ -+static char flip_table[256]; -+ -+void dsp_cancel_init_flip_bits() -+{ -+ int i,k; -+ -+ for (i = 0 ; i < 256 ; i++) { -+ unsigned char sample = 0 ; -+ for (k = 0; k<8; k++) { -+ if ( i & 1 << k ) sample |= 0x80 >> k; -+ } -+ flip_table[i] = sample; -+ } -+} -+ -+static unsigned char * flip_buf_bits ( unsigned char * buf , int len) -+{ -+ int i; -+ char * start = buf; -+ -+ for (i = 0 ; i < len; i++) { -+ buf[i] = flip_table[buf[i]]; -+ } -+ -+ return start; -+} -+ -+ -+ -+void -+dsp_cancel_tx(dsp_t *dsp, u8 *data, int len) -+{ -+ if (!dsp ) return ; -+ if (!data) return; -+ -+ if (dsp->txbuflen + len < ECHOCAN_BUFLEN) { -+ memcpy(&dsp->txbuf[dsp->txbuflen],data,len); -+ dsp->txbuflen+=len; -+ } else { -+ printk("ECHOCAN: TXBUF Overflow len:%d newlen:%d\n",dsp->txbuflen,len); -+ dsp->txbuflen=0; -+ } -+ -+} -+ -+void -+dsp_cancel_rx(dsp_t *dsp, u8 *data, int len) -+{ -+ if (!dsp ) return ; -+ if (!data) return; -+ -+ if (len <= dsp->txbuflen) { -+ char tmp[ECHOCAN_BUFLEN]; -+ -+ int delta=dsp->txbuflen-len; -+ -+ memcpy(tmp,&dsp->txbuf[len],delta); -+ -+ flip_buf_bits(data,len); -+ flip_buf_bits(dsp->txbuf,len); -+ bchdev_echocancel_chunk(dsp, data, dsp->txbuf, len); -+ flip_buf_bits(data,len); -+ -+ memcpy(dsp->txbuf,tmp,delta); -+ dsp->txbuflen=delta; -+ //dsp->txbuflen=0; -+ -+ //bchdev_echocancel_chunk(dsp, dsp->txbuf, data, len); -+ } else { -+ printk("ECHOCAN: TXBUF Underrun len:%d newlen:%d\n",dsp->txbuflen,len); -+ } -+ -+} -+ -+int -+dsp_cancel_init(dsp_t *dsp, int deftaps, int training, int delay) -+{ -+ -+ if (!dsp) return -1; -+ -+ printk("DSP_CANCEL_INIT called\n"); -+ -+ if (delay < 0) -+ { -+ printk("Disabling EC\n"); -+ dsp->cancel_enable = 0; -+ -+ dsp->txbuflen=0; -+ -+ bchdev_echocancel_deactivate(dsp); -+ -+ return(0); -+ } -+ -+ dsp->txbuflen=0; -+ dsp->rxbuflen=0; -+ -+ -+ bchdev_echocancel_activate(dsp,deftaps, training); -+ -+ printk("Enabling EC\n"); -+ dsp->cancel_enable = 1; -+ return(0); -+} -+ -+ -+ -+ -+ -+/*****************************************************/ -+#define __ECHO_STATE_MUTE (1 << 8) -+#define ECHO_STATE_IDLE (0) -+#define ECHO_STATE_PRETRAINING (1 | (__ECHO_STATE_MUTE)) -+#define ECHO_STATE_STARTTRAINING (2 | (__ECHO_STATE_MUTE)) -+#define ECHO_STATE_AWAITINGECHO (3 | (__ECHO_STATE_MUTE)) -+#define ECHO_STATE_TRAINING (4 | (__ECHO_STATE_MUTE)) -+#define ECHO_STATE_ACTIVE (5) -+ -+#define AMI_MASK 0x55 -+ -+ -+static unsigned char linear2alaw (short linear) -+{ -+ int mask; -+ int seg; -+ int pcm_val; -+ static int seg_end[8] = -+ { -+ 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF -+ }; -+ -+ pcm_val = linear; -+ if (pcm_val >= 0) -+ { -+ /* Sign (7th) bit = 1 */ -+ mask = AMI_MASK | 0x80; -+ } -+ else -+ { -+ /* Sign bit = 0 */ -+ mask = AMI_MASK; -+ pcm_val = -pcm_val; -+ } -+ -+ /* Convert the scaled magnitude to segment number. */ -+ for (seg = 0; seg < 8; seg++) -+ { -+ if (pcm_val <= seg_end[seg]) -+ break; -+ } -+ /* Combine the sign, segment, and quantization bits. */ -+ return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask; -+} -+ -+/*- End of function --------------------------------------------------------*/ -+ -+static short int alaw2linear (uint8_t alaw) -+{ -+ int i; -+ int seg; -+ -+ alaw ^= AMI_MASK; -+ i = ((alaw & 0x0F) << 4); -+ seg = (((int) alaw & 0x70) >> 4); -+ if (seg) -+ i = (i + 0x100) << (seg - 1); -+ return (short int) ((alaw & 0x80) ? i : -i); -+} -+ -+ -+/** @return string of given echo cancellation state */ -+char* bchdev_echocancel_statestr(uint16_t state) -+{ -+ switch(state) { -+ case ECHO_STATE_IDLE: -+ return "idle"; -+ break; -+ case ECHO_STATE_PRETRAINING: -+ return "pre-training"; -+ break; -+ case ECHO_STATE_STARTTRAINING: -+ return "transmit impulse"; -+ break; -+ case ECHO_STATE_AWAITINGECHO: -+ return "awaiting echo"; -+ break; -+ case ECHO_STATE_TRAINING: -+ return "training start"; -+ break; -+ case ECHO_STATE_ACTIVE: -+ return "training finished"; -+ break; -+ default: -+ return "unknown"; -+ } -+} -+ -+/** Changes state of echo cancellation to given state */ -+void bchdev_echocancel_setstate(dsp_t* dev, uint16_t state) -+{ -+ char* statestr = bchdev_echocancel_statestr(state); -+ -+ printk("bchdev: echo cancel state %d (%s)\n", state & 0xff, statestr); -+ if (state == ECHO_STATE_ACTIVE) -+ printk("bchdev: %d taps trained\n", dev->echolastupdate); -+ dev->echostate = state; -+} -+ -+static int buf_size=0; -+static int ec_timer=2000; -+//static int ec_timer=1000; -+ -+ -+/** Activates echo cancellation for the given bch_dev, device must have been locked before! */ -+int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int training) -+{ -+ int taps; -+ -+ if (! dev) return -EINVAL; -+ -+ if (dev->ec && dev->ecdis_rd && dev->ecdis_wr) { -+ // already active -+ return 0; -+ } -+ -+ if (deftaps>0) { -+ taps=deftaps; -+ } else { -+ taps=128; -+ } -+ -+ -+ switch (buf_size) { -+ case 0: taps += 0; break; -+ case 1: taps += 256-128; break; -+ case 2: taps += 512-128; break; -+ default: taps += 1024-128; -+ } -+ -+ if (!dev->ec) dev->ec = echo_can_create(taps, 0); -+ if (!dev->ec) { -+ return -ENOMEM; -+ } -+ -+ dev->echolastupdate = 0; -+ -+ if (!training) { -+ dev->echotimer=0; -+ bchdev_echocancel_setstate(dev, ECHO_STATE_IDLE); -+ } else { -+ if (training<10) -+ training= ec_timer; -+ -+ dev->echotimer = training; -+ bchdev_echocancel_setstate(dev, ECHO_STATE_PRETRAINING); -+ -+ } -+ -+ if (!dev->ecdis_rd) dev->ecdis_rd = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_KERNEL); -+ if (!dev->ecdis_rd) { -+ kfree(dev->ec); dev->ec = NULL; -+ return -ENOMEM; -+ } -+ echo_can_disable_detector_init(dev->ecdis_rd); -+ -+ if (!dev->ecdis_wr) dev->ecdis_wr = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_KERNEL); -+ if (!dev->ecdis_wr) { -+ kfree(dev->ec); dev->ec = NULL; -+ kfree(dev->ecdis_rd); dev->ecdis_rd = NULL; -+ return -ENOMEM; -+ } -+ echo_can_disable_detector_init(dev->ecdis_wr); -+ -+ return 0; -+} -+ -+/** Deactivates echo cancellation for the given bch_dev, device must have been locked before! */ -+void bchdev_echocancel_deactivate(dsp_t* dev) -+{ -+ if (! dev) return; -+ -+ //chan_misdn_log("bchdev: deactivating echo cancellation on port=%04x, chan=%02x\n", dev->stack->port, dev->channel); -+ -+ if (dev->ec) echo_can_free(dev->ec); -+ dev->ec = NULL; -+ -+ dev->echolastupdate = 0; -+ dev->echotimer = 0; -+ bchdev_echocancel_setstate(dev, ECHO_STATE_IDLE); -+ -+ if (dev->ecdis_rd) kfree(dev->ecdis_rd); -+ dev->ecdis_rd = NULL; -+ -+ if (dev->ecdis_wr) kfree(dev->ecdis_wr); -+ dev->ecdis_wr = NULL; -+} -+ -+/** Processes one TX- and one RX-packet with echocancellation */ -+void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size) -+{ -+ int16_t rxlin, txlin; -+ uint16_t pos; -+ -+ /* Perform echo cancellation on a chunk if requested */ -+ if (dev->ec) { -+ if (dev->echostate & __ECHO_STATE_MUTE) { -+ if (dev->echostate == ECHO_STATE_STARTTRAINING) { -+ // Transmit impulse now -+ txchunk[0] = linear2alaw(16384); -+ memset(txchunk+1, 0, size-1); -+ bchdev_echocancel_setstate(dev, ECHO_STATE_TRAINING); //AWAITINGECHO); -+ } else { -+ // train the echo cancellation -+ for (pos = 0; pos < size; pos++) { -+ rxlin = alaw2linear(rxchunk[pos]); -+ txlin = alaw2linear(txchunk[pos]); -+ if (dev->echostate == ECHO_STATE_PRETRAINING) { -+ if (dev->echotimer <= 0) { -+ dev->echotimer = 0; -+ bchdev_echocancel_setstate(dev, ECHO_STATE_STARTTRAINING); -+ } else { -+ dev->echotimer--; -+ } -+ } -+ if ((dev->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) { -+ dev->echolastupdate = 0; -+ bchdev_echocancel_setstate(dev, ECHO_STATE_TRAINING); -+ } -+ if (dev->echostate == ECHO_STATE_TRAINING) { -+ if (echo_can_traintap(dev->ec, dev->echolastupdate++, rxlin)) { -+ bchdev_echocancel_setstate(dev, ECHO_STATE_ACTIVE); -+ } -+ } -+ -+ rxchunk[pos] = linear2alaw(0); -+ txchunk[pos] = linear2alaw(0); -+ } -+ } -+ } else { -+ for (pos = 0; pos < size; pos++) { -+ rxlin = alaw2linear(rxchunk[pos]); -+ txlin = alaw2linear(txchunk[pos]); -+ -+ if (echo_can_disable_detector_update(dev->ecdis_rd, rxlin) || -+ echo_can_disable_detector_update(dev->ecdis_wr, txlin)) { -+ bchdev_echocancel_deactivate(dev); -+ printk("EC: Fax detected, EC disabled\n"); -+ return ; -+ } else { -+ rxlin = echo_can_update(dev->ec, txlin, rxlin); -+ rxchunk[pos] = linear2alaw(rxlin); -+ } -+ } -+ } -+ } -+} -+ -+/******************************************************/ -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_core.c mISDN/drivers/isdn/hardware/mISDN/dsp_core.c ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp_core.c 2005-01-29 17:15:21.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/dsp_core.c 2005-12-02 09:57:08.000000000 +0100 -@@ -42,17 +42,11 @@ - * v | - * +-----+-------------+-----+ - * |(3)(4) | -- * | | -- * | | - * | CMX | - * | | -- * | | -- * | | -- * | | - * | +-------------+ - * | | ^ - * | | | -- * | | | - * |+---------+| +----+----+ - * ||(1) || |(5) | - * || || | | -@@ -62,7 +56,6 @@ - * |+----+----+| +----+----+ - * +-----+-----+ ^ - * | | -- * | | - * v | - * +----+----+ +----+----+ - * |(5) | |(2) | -@@ -74,8 +67,18 @@ - * | ^ - * | | - * v | -+ * +----+-------------+----+ -+ * |(7) | -+ * | | -+ * | Echo Cancellation | -+ * | | -+ * | | -+ * +----+-------------+----+ -+ * | ^ -+ * | | -+ * v | - * +----+----+ +----+----+ -- * |(7) | |(7) | -+ * |(8) | |(8) | - * | | | | - * | Encrypt | | Decrypt | - * | | | | -@@ -115,6 +118,13 @@ - * data to/form upper layer may be swithed on/off individually without loosing - * features of CMX, Tones and DTMF. - * -+ * Echo Cancellation: Sometimes we like to cancel echo from the interface. -+ * Note that a VoIP call may not have echo caused by the IP phone. The echo -+ * is generated by the telephone line connected to it. Because the delay -+ * is high, it becomes an echo. RESULT: Echo Cachelation is required if -+ * both echo AND delay is applied to an interface. -+ * Remember that software CMX always generates a more or less delay. -+ * - * If all used features can be realized in hardware, and if transmit and/or - * receive data ist disabled, the card may not send/receive any data at all. - * Not receiving is usefull if only announcements are played. Not sending is -@@ -215,6 +225,9 @@ - printk(KERN_ERR "%s: failed to create tx packet\n", __FUNCTION__); - return; - } -+ /* if echo cancellation is enabled */ -+ if (dsp->cancel_enable) -+ dsp_cancel_tx(dsp, nskb->data, nskb->len); - /* crypt if enabled */ - if (dsp->bf_enable) - dsp_bf_encrypt(dsp, nskb->data, nskb->len); -@@ -380,6 +393,34 @@ - if (dsp_debug & DEBUG_DSP_CMX) - dsp_cmx_debug(dsp); - break; -+ case ECHOCAN_ON: /* turn echo calcellation on */ -+ -+ if (len<4) { -+ ret = -EINVAL; -+ break; -+ } -+ int ec_arr[2]; -+ -+ memcpy(&ec_arr,data,sizeof(ec_arr)); -+ -+ -+ printk("data[0]: %d data[1]: %d, len :%d\n",ec_arr[0], -+ ec_arr[1] ,len); -+ -+ if (dsp_debug & DEBUG_DSP_CORE) -+ printk(KERN_DEBUG "%s: turn echo cancelation on (delay=%d attenuation-shift=%d\n", __FUNCTION__, ec_arr[0], ec_arr[1]); -+ -+ ret = dsp_cancel_init(dsp, ec_arr[0], ec_arr[1] ,1); -+ -+ dsp_cmx_hardware(dsp->conf, dsp); -+ break; -+ case ECHOCAN_OFF: /* turn echo calcellation off */ -+ if (dsp_debug & DEBUG_DSP_CORE) -+ printk(KERN_DEBUG "%s: turn echo cancelation off\n", __FUNCTION__); -+ -+ ret = dsp_cancel_init(dsp, 0,0,-1); -+ dsp_cmx_hardware(dsp->conf, dsp); -+ break; - case BF_ENABLE_KEY: /* turn blowfish on */ - if (len<4 || len>56) { - ret = -EINVAL; -@@ -522,6 +563,9 @@ - /* decrypt if enabled */ - if (dsp->bf_enable) - dsp_bf_decrypt(dsp, skb->data, skb->len); -+ /* if echo cancellation is enabled */ -+ if (dsp->cancel_enable) -+ dsp_cancel_rx(dsp, skb->data, skb->len); - /* check if dtmf soft decoding is turned on */ - if (dsp->dtmf.software) { - digits = dsp_dtmf_goertzel_decode(dsp, skb->data, skb->len, (dsp_options&DSP_OPT_ULAW)?1:0); -@@ -919,6 +963,9 @@ - dsp_audio_generate_ulaw_samples(); - dsp_audio_generate_volume_changes(); - -+ -+ dsp_cancel_init_flip_bits(); -+ - /* init global lock */ - lock_HW_init(&dsp_lock); - -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp.h mISDN/drivers/isdn/hardware/mISDN/dsp.h ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/dsp.h 2005-01-29 17:15:31.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/dsp.h 2005-12-02 09:57:08.000000000 +0100 -@@ -40,6 +40,13 @@ - #include "memdbg.h" - #endif - -+#include "ecdis.h" -+#include "mec2.h" -+ -+//#include "mec.h" -+//#include "mec3.h" -+ -+ - extern int dsp_options; - extern int dsp_debug; - -@@ -109,6 +116,8 @@ - - #define DSP_DTMF_NPOINTS 102 - -+#define ECHOCAN_BUFLEN 4*128 -+ - typedef struct _dtmf_t { - int software; /* dtmf uses software decoding */ - int hardware; /* dtmf uses hardware decoding */ -@@ -120,6 +129,13 @@ - } dtmf_t; - - -+/************** -+ *Cancel Stuff* -+ ***************/ -+ -+void dsp_cancel_init_flip_bits(void); -+ -+ - /*************** - * tones stuff * - ***************/ -@@ -200,6 +216,25 @@ - u8 bf_crypt_inring[16]; - u8 bf_data_out[9]; - int bf_sync; -+ -+ /* echo cancellation stuff */ -+ int cancel_enable; -+ echo_can_state_t* ec; /**< == NULL: echo cancellation disabled; -+ != NULL: echo cancellation enabled */ -+ -+ echo_can_disable_detector_state_t* ecdis_rd; -+ echo_can_disable_detector_state_t* ecdis_wr; -+ -+ uint16_t echotimer; -+ uint16_t echostate; -+ uint16_t echolastupdate; -+ -+ char txbuf[ECHOCAN_BUFLEN]; -+ int txbuflen; -+ -+ char rxbuf[ECHOCAN_BUFLEN]; -+ int rxbuflen; -+ - } dsp_t; - - /* functions */ -@@ -228,4 +263,8 @@ - extern int dsp_bf_init(dsp_t *dsp, const u8 *key, unsigned int keylen); - extern void dsp_bf_cleanup(dsp_t *dsp); - -+extern void dsp_cancel_tx(dsp_t *dsp, u8 *data, int len); -+extern void dsp_cancel_rx(dsp_t *dsp, u8 *data, int len); -+extern int dsp_cancel_init(dsp_t *dsp, int taps, int training, int delay); -+ - -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.c mISDN/drivers/isdn/hardware/mISDN/ec.c ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.c 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/ec.c 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,105 @@ -+#include "mec2.h" -+#include "ec.h" -+ -+ -+ -+#define __ECHO_STATE_MUTE (1 << 8) -+#define ECHO_STATE_IDLE (0) -+#define ECHO_STATE_PRETRAINING (1 | (__ECHO_STATE_MUTE)) -+#define ECHO_STATE_STARTTRAINING (2 | (__ECHO_STATE_MUTE)) -+#define ECHO_STATE_AWAITINGECHO (3 | (__ECHO_STATE_MUTE)) -+#define ECHO_STATE_TRAINING (4 | (__ECHO_STATE_MUTE)) -+#define ECHO_STATE_ACTIVE (5) -+ -+#define AMI_MASK 0x55 -+ -+static unsigned char linear2alaw (short linear) -+{ -+ int mask; -+ int seg; -+ int pcm_val; -+ static int seg_end[8] = -+ { -+ 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF -+ }; -+ -+ pcm_val = linear; -+ if (pcm_val >= 0) -+ { -+ /* Sign (7th) bit = 1 */ -+ mask = AMI_MASK | 0x80; -+ } -+ else -+ { -+ /* Sign bit = 0 */ -+ mask = AMI_MASK; -+ pcm_val = -pcm_val; -+ } -+ -+ /* Convert the scaled magnitude to segment number. */ -+ for (seg = 0; seg < 8; seg++) -+ { -+ if (pcm_val <= seg_end[seg]) -+ break; -+ } -+ /* Combine the sign, segment, and quantization bits. */ -+ return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask; -+} -+/*- End of function --------------------------------------------------------*/ -+ -+static short int alaw2linear (uint8_t alaw) -+{ -+ int i; -+ int seg; -+ -+ alaw ^= AMI_MASK; -+ i = ((alaw & 0x0F) << 4); -+ seg = (((int) alaw & 0x70) >> 4); -+ if (seg) -+ i = (i + 0x100) << (seg - 1); -+ return (short int) ((alaw & 0x80) ? i : -i); -+} -+ -+ -+void ec_chunk(struct echo_can_s *echo_can, unsigned char *rxchunk, const unsigned char *txchunk, int chunk_size) -+{ -+ short rxlin, txlin; -+ int x; -+ //unsigned long flags; -+ /* Perform echo cancellation on a chunk if necessary */ -+ if (echo_can->ec) { -+ if (echo_can->echostate & __ECHO_STATE_MUTE) { -+ /* Special stuff for training the echo can */ -+ for (x=0;x< chunk_size;x++) { -+ rxlin = alaw2linear(rxchunk[x]); -+ txlin = alaw2linear(txchunk[x]); -+ if (echo_can->echostate == ECHO_STATE_PRETRAINING) { -+ if (--echo_can->echotimer <= 0) { -+ echo_can->echotimer = 0; -+ echo_can->echostate = ECHO_STATE_STARTTRAINING; -+ } -+ } -+ if ((echo_can->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) { -+ echo_can->echolastupdate = 0; -+ echo_can->echostate = ECHO_STATE_TRAINING; -+ } -+ if (echo_can->echostate == ECHO_STATE_TRAINING) { -+ if (echo_can_traintap(echo_can->ec, echo_can->echolastupdate++, rxlin)) { -+#if 0 -+ printf("Finished training (%d taps trained)!\n", echo_can->echolastupdate); -+#endif -+ echo_can->echostate = ECHO_STATE_ACTIVE; -+ } -+ } -+ rxlin = 0; -+ rxchunk[x] = linear2alaw((int)rxlin); -+ } -+ } else { -+ for (x=0;x<chunk_size;x++) { -+ rxlin = alaw2linear(rxchunk[x]); -+ rxlin = echo_can_update(echo_can->ec, alaw2linear(txchunk[x]), rxlin); -+ rxchunk[x] = linear2alaw((int)rxlin); -+ } -+ } -+ } -+} -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/ecdis.h mISDN/drivers/isdn/hardware/mISDN/ecdis.h ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/ecdis.h 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/ecdis.h 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,118 @@ -+/* -+ * SpanDSP - a series of DSP components for telephony -+ * -+ * ec_disable_detector.h - A detector which should eventually meet the -+ * G.164/G.165 requirements for detecting the -+ * 2100Hz echo cancellor disable tone. -+ * -+ * Written by Steve Underwood <steveu@coppice.org> -+ * -+ * Copyright (C) 2001 Steve Underwood -+ * -+ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ */ -+ -+#include "biquad.h" -+ -+typedef struct -+{ -+ biquad2_state_t notch; -+ int notch_level; -+ int channel_level; -+ int tone_present; -+ int tone_cycle_duration; -+ int good_cycles; -+ int hit; -+} echo_can_disable_detector_state_t; -+ -+ -+#define FALSE 0 -+#define TRUE (!FALSE) -+ -+static inline void echo_can_disable_detector_init (echo_can_disable_detector_state_t *det) -+{ -+ /* Elliptic notch */ -+ /* This is actually centred at 2095Hz, but gets the balance we want, due -+ to the asymmetric walls of the notch */ -+ biquad2_init (&det->notch, -+ (int32_t) (-0.7600000*32768.0), -+ (int32_t) (-0.1183852*32768.0), -+ (int32_t) (-0.5104039*32768.0), -+ (int32_t) ( 0.1567596*32768.0), -+ (int32_t) ( 1.0000000*32768.0)); -+ -+ det->channel_level = 0; -+ det->notch_level = 0; -+ det->tone_present = FALSE; -+ det->tone_cycle_duration = 0; -+ det->good_cycles = 0; -+ det->hit = 0; -+} -+/*- End of function --------------------------------------------------------*/ -+ -+static inline int echo_can_disable_detector_update (echo_can_disable_detector_state_t *det, -+ int16_t amp) -+{ -+ int16_t notched; -+ -+ notched = biquad2 (&det->notch, amp); -+ /* Estimate the overall energy in the channel, and the energy in -+ the notch (i.e. overall channel energy - tone energy => noise). -+ Use abs instead of multiply for speed (is it really faster?). -+ Damp the overall energy a little more for a stable result. -+ Damp the notch energy a little less, so we don't damp out the -+ blip every time the phase reverses */ -+ det->channel_level += ((abs(amp) - det->channel_level) >> 5); -+ det->notch_level += ((abs(notched) - det->notch_level) >> 4); -+ if (det->channel_level > 280) -+ { -+ /* There is adequate energy in the channel. Is it mostly at 2100Hz? */ -+ if (det->notch_level*6 < det->channel_level) -+ { -+ /* The notch says yes, so we have the tone. */ -+ if (!det->tone_present) -+ { -+ /* Do we get a kick every 450+-25ms? */ -+ if (det->tone_cycle_duration >= 425*8 -+ && -+ det->tone_cycle_duration <= 475*8) -+ { -+ det->good_cycles++; -+ if (det->good_cycles > 2) -+ det->hit = TRUE; -+ } -+ det->tone_cycle_duration = 0; -+ } -+ det->tone_present = TRUE; -+ } -+ else -+ { -+ det->tone_present = FALSE; -+ } -+ det->tone_cycle_duration++; -+ } -+ else -+ { -+ det->tone_present = FALSE; -+ det->tone_cycle_duration = 0; -+ det->good_cycles = 0; -+ } -+ return det->hit; -+} -+/*- End of function --------------------------------------------------------*/ -+/*- End of file ------------------------------------------------------------*/ -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.h mISDN/drivers/isdn/hardware/mISDN/ec.h ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/ec.h 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/ec.h 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,12 @@ -+ -+ -+ -+struct echo_can_s { -+ int echostate; -+ int echotimer; -+ int echolastupdate; -+ echo_can_state_t *ec; -+}; -+ -+ -+ -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c 2005-01-31 18:24:03.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c 2005-12-02 09:57:08.000000000 +0100 -@@ -136,7 +136,7 @@ - static int nt_t1_count[] = { 480, 240, 120, 60, 30, 15, 8, 4 }; - #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ - #define CLKDEL_NT 0x0c /* CLKDEL in NT mode (0x60 MUST not be included!) */ --static u_char silence = 0xff; /* silence by LAW */ -+static u_char mysilence = 0xff; /* silence by LAW */ - - /* enable 32 bit fifo access (PC usage) */ - #define FIFO_32BIT_ACCESS -@@ -903,11 +903,11 @@ - bch->tx_idx = bch->tx_len = 0; - } - /* now we have no more data, so in case of transparent, -- * we set the last byte in fifo to 'silence' in case we will get -+ * we set the last byte in fifo to 'mysilence' in case we will get - * no more data at all. this prevents sending an undefined value. - */ - if (!hdlc) -- HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); -+ HFC_outb_(hc, A_FIFO_DATA0_NOINC, mysilence); - } - - -@@ -1551,7 +1551,7 @@ - HFC_outb(hc, A_IRQ_MSK, 0); - HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); - HFC_wait(hc); -- HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); /* tx silence */ -+ HFC_outb_(hc, A_FIFO_DATA0_NOINC, mysilence); /* tx silence */ - /* enable RX fifo */ - HFC_outb(hc, R_FIFO, (ch<<1)|1); - HFC_wait(hc); -@@ -1692,7 +1692,7 @@ - - /* if off */ - if (len <= 0) { -- HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); -+ HFC_outb_(hc, A_FIFO_DATA0_NOINC, mysilence); - if (hc->chan[ch].slot_tx>=0) { - if (debug & DEBUG_HFCMULTI_MODE) - printk(KERN_DEBUG "%s: connecting PCM due to no more TONE: channel %d slot_tx %d\n", __FUNCTION__, ch, hc->chan[ch].slot_tx); -@@ -2183,7 +2183,7 @@ - ret = 0; - break; - -- /* set silence */ -+ /* set mysilence */ - case HW_SPL_LOOP_OFF: - if (debug & DEBUG_HFCMULTI_MSG) - printk(KERN_DEBUG "%s: HW_SPL_LOOP_OFF\n", __FUNCTION__); -@@ -2799,7 +2799,13 @@ - if (debug & DEBUG_HFCMULTI_INIT) - printk(KERN_DEBUG "setup_pci(): investigating card entry %d (looking for type %d)\n", i, hc->type); - inuse: -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) -+ tmp_dev = pci_get_subsys(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_sub, id_list[i].device_sub, tmp_dev); -+#else - tmp_dev = pci_find_subsys(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_sub, id_list[i].device_sub, tmp_dev); -+#endif -+ - if (tmp_dev) { - /* skip if already in use */ - list_for_each_entry_safe(hc_tmp, next, &HFCM_obj.ilist, list) { -@@ -3318,9 +3324,9 @@ - hc->type = type[HFC_cnt] & 0xff; - if (type[HFC_cnt] & 0x100) { - test_and_set_bit(HFC_CHIP_ULAW, &hc->chip); -- silence = 0xff; /* ulaw silence */ -+ mysilence = 0xff; /* ulaw silence */ - } else -- silence = 0x2a; /* alaw silence */ -+ mysilence = 0x2a; /* alaw silence */ - if (type[HFC_cnt] & 0x200) - test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); - // if ((type[HFC_cnt]&0x400) && hc->type==4) -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c 2005-03-26 11:21:39.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/l3_udss1.c 2005-12-02 09:57:08.000000000 +0100 -@@ -1202,6 +1202,14 @@ - err = check_infoelements(pc, skb, ie_PROGRESS); - if (err) - l3dss1_std_ie_err(pc, err); -+ /* START: patch by steinwej - http://www.beronet.com/bugs/bug_view_page.php?bug_id=0000095 */ -+ /* clear T310 if running */ -+ L3DelTimer(&pc->timer); -+ if (pc->t303skb) { -+ dev_kfree_skb(pc->t303skb); -+ pc->t303skb = NULL; -+ } -+ /* END */ - if (ERR_IE_COMPREHENSION != err) { - if (mISDN_l3up(pc, CC_PROGRESS | INDICATION, skb)) - dev_kfree_skb(skb); -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile mISDN/drivers/isdn/hardware/mISDN/Makefile ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile 2005-06-05 14:44:10.000000000 +0200 -+++ mISDN/drivers/isdn/hardware/mISDN/Makefile 2005-12-05 19:03:11.000000000 +0100 -@@ -30,6 +30,7 @@ - - ifdef CONFIG_MISDN_SPEEDFAX - obj-$(CONFIG_MISDN_DRV) += sedlfax.o -+obj-$(CONFIG_MISDN_DRV) += faxl3.o - endif - - ifdef CONFIG_MISDN_W6692 -@@ -70,8 +71,6 @@ - asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \ - supp_serv.o - mISDN_dtmf-objs := dtmf.o --mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o -+mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_cancel.o - mISDN_x25dte-objs := x25_dte.o x25_l3.o - I4LmISDN-objs := i4l_mISDN.o -- --include Rules.mISDN -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6 mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6 ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6 2005-06-05 14:44:10.000000000 +0200 -+++ mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6 2005-12-02 09:57:08.000000000 +0100 -@@ -71,6 +71,6 @@ - asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \ - supp_serv.o - mISDN_dtmf-objs := dtmf.o --mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o -+mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_cancel.o - mISDN_x25dte-objs := x25_dte.o x25_l3.o - I4LmISDN-objs := i4l_mISDN.o -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2_const.h mISDN/drivers/isdn/hardware/mISDN/mec2_const.h ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2_const.h 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/mec2_const.h 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,25 @@ -+/* -+ Important constants for tuning mec2 echo can -+ */ -+#ifndef _MEC2_CONST_H -+#define _MEC2_CONST_H -+ -+ -+/* Convergence speed -- higher means slower */ -+#define DEFAULT_BETA1_I 2048 -+#define DEFAULT_SIGMA_LY_I 7 -+#define DEFAULT_SIGMA_LU_I 7 -+#define DEFAULT_ALPHA_ST_I 5 -+#define DEFAULT_ALPHA_YT_I 5 -+#define DEFAULT_CUTOFF_I 128 -+#define DEFAULT_HANGT 600 -+#define DEFAULT_SUPPR_I 16 -+#define MIN_UPDATE_THRESH_I 4096 -+#define DEFAULT_M 16 -+#define SUPPR_FLOOR -64 -+#define SUPPR_CEIL -24 -+#define RES_SUPR_FACTOR -20 -+#define AGGRESSIVE_HCNTR 160 /* 20ms */ -+ -+#endif /* _MEC2_CONST_H */ -+ -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2.h mISDN/drivers/isdn/hardware/mISDN/mec2.h ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec2.h 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/mec2.h 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,409 @@ -+/* -+ * Mark's Second Echo Canceller -+ * -+ * Copyright (C) 2002, Digium, Inc. -+ * -+ * This program is free software and may be used and -+ * distributed according to the terms of the GNU -+ * General Public License, incorporated herein by -+ * reference. -+ * -+ */ -+#ifndef _MARK2_ECHO_H -+#define _MARK2_ECHO_H -+ -+#ifdef __KERNEL__ -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#define MALLOC(a) kmalloc((a), GFP_KERNEL) -+#define FREE(a) kfree(a) -+#else -+#include <stdlib.h> -+#include <unistd.h> -+#include <stdint.h> -+#include <string.h> -+#include <math.h> -+#define MALLOC(a) malloc(a) -+#define FREE(a) free(a) -+#endif -+ -+/* Get optimized routines for math */ -+#include "arith.h" -+ -+#ifndef NULL -+#define NULL 0 -+#endif -+#ifndef FALSE -+#define FALSE 0 -+#endif -+#ifndef TRUE -+#define TRUE (!FALSE) -+#endif -+ -+#include "mec2_const.h" -+ -+/* Circular buffer definition */ -+typedef struct { -+ int idx_d; -+ int size_d; -+ short *buf_d; /* Twice as large as we need */ -+} echo_can_cb_s; -+ -+// class definition -+// -+typedef struct { -+ /* Echo canceller definition */ -+ -+ /* absolute time */ -+ int i_d; -+ -+ /* pre-computed constants */ -+ -+ int N_d; -+ int beta2_i; -+ -+ // declare accumulators for power computations -+ // -+ int Ly_i; -+ int Lu_i; -+ -+ // declare an accumulator for the near-end signal detector -+ // -+ int s_tilde_i; -+ int HCNTR_d; -+ -+ // circular buffers and coefficients -+ // -+ int *a_i; -+ short *a_s; -+ echo_can_cb_s y_s; -+ echo_can_cb_s s_s; -+ echo_can_cb_s u_s; -+ echo_can_cb_s y_tilde_s; -+ int y_tilde_i; -+ -+ /* Max memory */ -+ short max_y_tilde; -+ int max_y_tilde_pos; -+ -+} echo_can_state_t; -+ -+static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) -+{ -+ cb->buf_d = (short *)where; -+ cb->idx_d = 0; -+ cb->size_d = len; -+} -+ -+static inline void add_cc_s(echo_can_cb_s *cb, short newval) -+{ -+ /* Can't use modulus because N+M isn't a power of two (generally) */ -+ cb->idx_d--; -+ if (cb->idx_d < (int)0) -+ {cb->idx_d += cb->size_d;} -+ /* Load two copies into memory */ -+ cb->buf_d[cb->idx_d] = newval; -+ cb->buf_d[cb->idx_d + cb->size_d] = newval; -+} -+ -+static inline short get_cc_s(echo_can_cb_s *cb, int pos) -+{ -+ /* Load two copies into memory */ -+ return cb->buf_d[cb->idx_d + pos]; -+} -+ -+static inline void init_cc(echo_can_state_t *ec, int N, int maxy, int maxu) { -+ -+ void *ptr = ec; -+ unsigned long tmp; -+ /* double-word align past end of state */ -+ ptr += sizeof(echo_can_state_t); -+ tmp = (unsigned long)ptr; -+ tmp += 3; -+ tmp &= ~3L; -+ ptr = (void *)tmp; -+ -+ // reset parameters -+ // -+ ec->N_d = N; -+ ec->beta2_i = DEFAULT_BETA1_I; -+ -+ // allocate coefficient memory -+ // -+ ec->a_i = ptr; -+ ptr += (sizeof(int) * ec->N_d); -+ ec->a_s = ptr; -+ ptr += (sizeof(short) * ec->N_d); -+ -+ /* Reset Y circular buffer (short version) */ -+ init_cb_s(&ec->y_s, maxy, ptr); -+ ptr += (sizeof(short) * (maxy) * 2); -+ -+ /* Reset Sig circular buffer (short version for FIR filter) */ -+ init_cb_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr); -+ ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2); -+ -+ init_cb_s(&ec->u_s, maxu, ptr); -+ ptr += (sizeof(short) * maxu * 2); -+ -+ // allocate a buffer for the reference signal power computation -+ // -+ init_cb_s(&ec->y_tilde_s, ec->N_d, ptr); -+ -+ -+ // reset absolute time -+ // -+ ec->i_d = (int)0; -+ -+ // reset the power computations (for y and u) -+ // -+ ec->Ly_i = DEFAULT_CUTOFF_I; -+ ec->Lu_i = DEFAULT_CUTOFF_I; -+ -+ // reset the near-end speech detector -+ // -+ ec->s_tilde_i = 0; -+ ec->HCNTR_d = (int)0; -+ -+ // exit gracefully -+ // -+} -+ -+static inline void echo_can_free(echo_can_state_t *ec) -+{ -+ FREE(ec); -+} -+ -+static inline short echo_can_update(echo_can_state_t *ec, short iref, short isig) { -+ -+ /* declare local variables that are used more than once -+ */ -+ int k; -+ int rs; -+ short u; -+ int Py_i; -+ int two_beta_i; -+ -+ /*************************************************************************** -+ // -+ // flow A on pg. 428 -+ // -+ ***************************************************************************/ -+ -+ /* eq. (16): high-pass filter the input to generate the next value; -+ // push the current value into the circular buffer -+ // -+ // sdc_im1_d = sdc_d; -+ // sdc_d = sig; -+ // s_i_d = sdc_d; -+ // s_d = s_i_d; -+ // s_i_d = (float)(1.0 - gamma_d) * s_i_d -+ + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); */ -+ -+ -+ /* Delete last sample from power estimate */ -+ ec->y_tilde_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1 )) >> DEFAULT_ALPHA_YT_I; -+ /* push the reference data onto the circular buffer */ -+ add_cc_s(&ec->y_s, iref); -+ -+ /* eq. (2): compute r in fixed-point */ -+ rs = CONVOLVE2(ec->a_s, ec->y_s.buf_d + ec->y_s.idx_d, ec->N_d); -+ rs >>= 15; -+ -+ /* eq. (3): compute the output value (see figure 3) and the error -+ // note: the error is the same as the output signal when near-end -+ // speech is not present -+ */ -+ u = isig - rs; -+ -+ add_cc_s(&ec->u_s, u); -+ -+ -+ -+ /* Delete oldest part of received s_tilde */ -+ ec->s_tilde_i -= abs(get_cc_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1 )); -+ -+ /* push the signal on the circular buffer, too */ -+ add_cc_s(&ec->s_s, isig); -+ ec->s_tilde_i += abs(isig); -+ ec->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_YT_I; -+ -+ /* Add to our list of recent y_tilde's */ -+ add_cc_s(&ec->y_tilde_s, ec->y_tilde_i); -+ -+ /**************************************************************************** -+ // -+ // flow B on pg. 428 -+ // -+ ****************************************************************************/ -+ -+ /* compute the new convergence factor -+ */ -+ Py_i = (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * (ec->Ly_i >> DEFAULT_SIGMA_LY_I); -+ Py_i >>= 15; -+ if (ec->HCNTR_d > 0) { -+ Py_i = (1 << 15); -+ } -+ -+#if 0 -+ printf("Py: %e, Py_i: %e\n", Py, Py_i * AMPL_SCALE_1); -+#endif -+ -+ /* Vary rate of adaptation depending on position in the file -+ // Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech -+ // has begun of the file to allow the echo cancellor to estimate the -+ // channel accurately -+ */ -+#if 0 -+ if (ec->start_speech_d != 0 ){ -+ if ( ec->i_d > (DEFAULT_T0 + ec->start_speech_d)*(SAMPLE_FREQ) ){ -+ ec->beta2_d = max_cc_float(MIN_BETA, -+ DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((ec->i_d/(float)SAMPLE_FREQ) - -+ DEFAULT_T0 - -+ ec->start_speech_d))); -+ } -+ } -+ else {ec->beta2_d = DEFAULT_BETA1;} -+#endif -+ -+ ec->beta2_i = DEFAULT_BETA1_I; /* Fixed point, inverted */ -+ -+ two_beta_i = (ec->beta2_i * Py_i) >> 15; /* Fixed point version, inverted */ -+ if (!two_beta_i) -+ two_beta_i++; -+ -+ /* Update Lu_i (Suppressed power estimate) */ -+ ec->Lu_i -= abs(get_cc_s(&ec->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1 )) ; -+ ec->Lu_i += abs(u); -+ -+ /* eq. (10): update power estimate of the reference -+ */ -+ ec->Ly_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ; -+ ec->Ly_i += abs(iref); -+ -+ if (ec->Ly_i < DEFAULT_CUTOFF_I) -+ ec->Ly_i = DEFAULT_CUTOFF_I; -+ -+#if 0 -+ printf("Float: %e, Int: %e\n", ec->Ly_d, (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * AMPL_SCALE_1); -+#endif -+ -+ if (ec->y_tilde_i > ec->max_y_tilde) { -+ /* New highest y_tilde with full life */ -+ ec->max_y_tilde = ec->y_tilde_i; -+ ec->max_y_tilde_pos = ec->N_d - 1; -+ } else if (--ec->max_y_tilde_pos < 0) { -+ /* Time to find new max y tilde... */ -+ ec->max_y_tilde = MAX16(ec->y_tilde_s.buf_d + ec->y_tilde_s.idx_d, ec->N_d, &ec->max_y_tilde_pos); -+ } -+ -+ if ((ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > ec->max_y_tilde) -+ { -+ ec->HCNTR_d = DEFAULT_HANGT; -+ } -+ else if (ec->HCNTR_d > (int)0) -+ { -+ ec->HCNTR_d--; -+ } -+ -+ /* update coefficients if no near-end speech and we have enough signal -+ * to bother trying to update. -+ */ -+ if (!ec->HCNTR_d && !(ec->i_d % DEFAULT_M) && -+ (ec->Lu_i > MIN_UPDATE_THRESH_I)) { -+ // loop over all filter coefficients -+ // -+ for (k=0; k<ec->N_d; k++) { -+ -+ // eq. (7): compute an expectation over M_d samples -+ // -+ int grad2; -+ grad2 = CONVOLVE2(ec->u_s.buf_d + ec->u_s.idx_d, -+ ec->y_s.buf_d + ec->y_s.idx_d + k, DEFAULT_M); -+ // eq. (7): update the coefficient -+ // -+ ec->a_i[k] += grad2 / two_beta_i; -+ ec->a_s[k] = ec->a_i[k] >> 16; -+ } -+ } -+ -+ /* paragraph below eq. (15): if no near-end speech, -+ // check for residual error suppression -+ */ -+#ifndef NO_ECHO_SUPPRESSOR -+#ifdef AGGRESSIVE_SUPPRESSOR -+ if ((ec->HCNTR_d < AGGRESSIVE_HCNTR) && (ec->Ly_i > (ec->Lu_i << 1))) { -+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1); -+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1); -+ } -+#else -+ if ((ec->HCNTR_d == 0) && ((ec->Ly_i/(ec->Lu_i + 1)) > DEFAULT_SUPPR_I)) { -+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1); -+ } -+#endif -+#endif -+ -+#if 0 -+ if ((ec->HCNTR_d == 0) && ((ec->Lu_d/ec->Ly_d) < DEFAULT_SUPPR) && -+ (ec->Lu_d/ec->Ly_d > EC_MIN_DB_VALUE)) { -+ suppr_factor = (10/(float)(SUPPR_FLOOR-SUPPR_CEIL))*log(ec->Lu_d/ec->Ly_d) -+ - SUPPR_CEIL/(float)(SUPPR_FLOOR - SUPPR_CEIL); -+ -+ u_suppr = pow(10.0,(suppr_factor)*RES_SUPR_FACTOR/10.0)*u_suppr; -+ -+ } -+#endif -+ ec->i_d++; -+ return u; -+} -+ -+static inline echo_can_state_t *echo_can_create(int len, int adaption_mode) -+{ -+ echo_can_state_t *ec; -+ int maxy; -+ int maxu; -+ maxy = len + DEFAULT_M; -+ maxu = DEFAULT_M; -+ if (maxy < (1 << DEFAULT_ALPHA_YT_I)) -+ maxy = (1 << DEFAULT_ALPHA_YT_I); -+ if (maxy < (1 << DEFAULT_SIGMA_LY_I)) -+ maxy = (1 << DEFAULT_SIGMA_LY_I); -+ if (maxu < (1 << DEFAULT_SIGMA_LU_I)) -+ maxu = (1 << DEFAULT_SIGMA_LU_I); -+ ec = (echo_can_state_t *)MALLOC(sizeof(echo_can_state_t) + -+ 4 + /* align */ -+ sizeof(int) * len + /* a_i */ -+ sizeof(short) * len + /* a_s */ -+ 2 * sizeof(short) * (maxy) + /* y_s */ -+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */ -+ 2 * sizeof(short) * (maxu) + /* u_s */ -+ 2 * sizeof(short) * len); /* y_tilde_s */ -+ if (ec) { -+ memset(ec, 0, sizeof(echo_can_state_t) + -+ 4 + /* align */ -+ sizeof(int) * len + /* a_i */ -+ sizeof(short) * len + /* a_s */ -+ 2 * sizeof(short) * (maxy) + /* y_s */ -+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */ -+ 2 * sizeof(short) * (maxu) + /* u_s */ -+ 2 * sizeof(short) * len); /* y_tilde_s */ -+ init_cc(ec, len, maxy, maxu); -+ } -+ return ec; -+} -+ -+static inline int echo_can_traintap(echo_can_state_t *ec, int pos, short val) -+{ -+ /* Reset hang counter to avoid adjustments after -+ initial forced training */ -+ ec->HCNTR_d = ec->N_d << 1; -+ if (pos >= ec->N_d) -+ return 1; -+ ec->a_i[pos] = val << 17; -+ ec->a_s[pos] = val << 1; -+ if (++pos >= ec->N_d) -+ return 1; -+ return 0; -+} -+ -+#endif -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec3.h mISDN/drivers/isdn/hardware/mISDN/mec3.h ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec3.h 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/mec3.h 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,243 @@ -+/* -+ * Mark's Third Echo Canceller -+ * -+ * Copyright (C) 2003, Digium, Inc. -+ * -+ * This program is free software and may be used -+ * and distributed under the terms of the GNU General Public -+ * License, incorporated herein by reference. -+ * -+ * Dedicated to the crew of the Columbia, STS-107 for their -+ * bravery and courageous sacrifice for science. -+ * -+ */ -+ -+#ifndef _MARK3_ECHO_H -+#define _MARK3_ECHO_H -+ -+ -+ -+#ifdef __KERNEL__ -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#define MALLOC(a) kmalloc((a), GFP_KERNEL) -+#define FREE(a) kfree(a) -+#else -+#include <stdlib.h> -+#include <unistd.h> -+#include <stdint.h> -+#include <string.h> -+#include <math.h> -+#define MALLOC(a) malloc(a) -+#define FREE(a) free(a) -+#endif -+ -+/* Features */ -+ -+/* -+ * DO_BACKUP -- Backup coefficients, and revert in the presense of double talk to try to prevent -+ * them from diverging during the ramp-up before the DTD kicks in -+ */ -+/* #define DO_BACKUP */ -+ -+#define STEP_SHIFT 2 /* Convergence rate higher = slower / better (as a shift) */ -+ -+#define SIGMA_REF_PWR 655 /* Keep denominator from being 0 */ -+ -+#define MIN_TX_ENERGY 256 /* Must have at least this much reference */ -+#define MIN_RX_ENERGY 32 /* Must have at least this much receive energy */ -+ -+#define MAX_ATTENUATION_SHIFT 6 /* Maximum amount of loss we care about */ -+#define MAX_BETA 1024 -+ -+#define SUPPR_SHIFT 4 /* Amount of loss at which we suppress audio */ -+ -+#define HANG_TIME 600 /* Hangover time */ -+ -+#define NTAPS 2048 /* Maximum number of echo can taps */ -+ -+#define BACKUP 256 /* Backup every this number of samples */ -+ -+#define POWER_OFFSET 5 /* Shift power by this amount to be sure we don't overflow the -+ reference power. Higher = less likely to overflow, lower = more accurage */ -+ -+#include "arith.h" -+ -+typedef struct { -+ short buf[NTAPS * 2]; -+ short max; -+ int maxexp; -+} cbuf_s; -+ -+typedef struct { -+ short a_s[NTAPS]; /* Coefficients in shorts */ -+ int a_i[NTAPS]; /* Coefficients in ints*/ -+#ifdef DO_BACKUP -+ int b_i[NTAPS]; /* Coefficients (backup1) */ -+ int c_i[NTAPS]; /* Coefficients (backup2) */ -+#endif -+ cbuf_s ref; /* Reference excitation */ -+ cbuf_s sig; /* Signal (echo + near end + noise) */ -+ cbuf_s e; /* Error */ -+ int refpwr; /* Reference power */ -+ int taps; /* Number of taps */ -+ int tappwr; /* Power of taps */ -+ int hcntr; /* Hangtime counter */ -+ int pos; /* Position in curcular buffers */ -+ int backup; /* Backup timer */ -+} echo_can_state_t; -+ -+static inline void echo_can_free(echo_can_state_t *ec) -+{ -+ FREE(ec); -+} -+ -+static inline void buf_add(cbuf_s *b, short sample, int pos, int taps) -+{ -+ /* Store and keep track of maxima */ -+ int x; -+ b->buf[pos] = sample; -+ b->buf[pos + taps] = sample; -+ if (sample > b->max) { -+ b->max = sample; -+ b->maxexp = taps; -+ } else { -+ b->maxexp--; -+ if (!b->maxexp) { -+ b->max = 0; -+ for (x=0;x<taps;x++) -+ if (b->max < abs(b->buf[pos + x])) { -+ b->max = abs(b->buf[pos + x]); -+ b->maxexp = x + 1; -+ } -+ } -+ } -+} -+ -+static inline short echo_can_update(echo_can_state_t *ec, short ref, short sig) -+{ -+ int x; -+ short u; -+ int refpwr; -+ int beta; /* Factor */ -+ int se; /* Simulated echo */ -+#ifdef DO_BACKUP -+ if (!ec->backup) { -+ /* Backup coefficients periodically */ -+ ec->backup = BACKUP; -+ memcpy(ec->c_i,ec->b_i,sizeof(ec->c_i)); -+ memcpy(ec->b_i,ec->a_i,sizeof(ec->b_i)); -+ } else -+ ec->backup--; -+#endif -+ /* Remove old samples from reference power calculation */ -+ ec->refpwr -= ((ec->ref.buf[ec->pos] * ec->ref.buf[ec->pos]) >> POWER_OFFSET); -+ -+ /* Store signal and reference */ -+ buf_add(&ec->ref, ref, ec->pos, ec->taps); -+ buf_add(&ec->sig, sig, ec->pos, ec->taps); -+ -+ /* Add new reference power */ -+ ec->refpwr += ((ec->ref.buf[ec->pos] * ec->ref.buf[ec->pos]) >> POWER_OFFSET); -+ -+ -+ /* Calculate simulated echo */ -+ se = CONVOLVE2(ec->a_s, ec->ref.buf + ec->pos, ec->taps); -+ se >>= 15; -+ -+ u = sig - se; -+ if (ec->hcntr) -+ ec->hcntr--; -+ -+ /* Store error */ -+ buf_add(&ec->e, sig, ec->pos, ec->taps); -+ if ((ec->ref.max > MIN_TX_ENERGY) && -+ (ec->sig.max > MIN_RX_ENERGY) && -+ (ec->e.max > (ec->ref.max >> MAX_ATTENUATION_SHIFT))) { -+ /* We have sufficient energy */ -+ if (ec->sig.max < (ec->ref.max >> 1)) { -+ /* No double talk */ -+ if (!ec->hcntr) { -+ refpwr = ec->refpwr >> (16 - POWER_OFFSET); -+ if (refpwr < SIGMA_REF_PWR) -+ refpwr = SIGMA_REF_PWR; -+ beta = (u << 16) / refpwr; -+ beta >>= STEP_SHIFT; -+ if (beta > MAX_BETA) -+ beta = 0; -+ if (beta < -MAX_BETA) -+ beta = 0; -+ /* Update coefficients */ -+ for (x=0;x<ec->taps;x++) { -+ ec->a_i[x] += beta * ec->ref.buf[ec->pos + x]; -+ ec->a_s[x] = ec->a_i[x] >> 16; -+ } -+ } -+ } else { -+#ifdef DO_BACKUP -+ if (!ec->hcntr) { -+ /* Our double talk detector is turning on for the first time. Revert -+ our coefficients, since we're probably well into the double talk by now */ -+ memcpy(ec->a_i, ec->c_i, sizeof(ec->a_i)); -+ for (x=0;x<ec->taps;x++) { -+ ec->a_s[x] = ec->a_i[x] >> 16; -+ } -+ } -+#endif -+ /* Reset hang-time counter, and prevent backups */ -+ ec->hcntr = HANG_TIME; -+#ifdef DO_BACKUP -+ ec->backup = BACKUP; -+#endif -+ } -+ } -+#ifndef NO_ECHO__SUPPRESSOR -+ if (ec->e.max < (ec->ref.max >> SUPPR_SHIFT)) { -+ /* Suppress residual echo */ -+ u *= u; -+ u >>= 16; -+ } -+#endif -+ ec->pos--; -+ if (ec->pos < 0) -+ ec->pos = ec->taps-1; -+ return u; -+} -+ -+static inline echo_can_state_t *echo_can_create(int taps, int adaption_mode) -+{ -+ echo_can_state_t *ec; -+ int x; -+ -+ //taps = NTAPS; -+ ec = MALLOC(sizeof(echo_can_state_t)); -+ if (ec) { -+ memset(ec, 0, sizeof(echo_can_state_t)); -+ ec->taps = taps; -+ ec->pos = ec->taps-1; -+ for (x=0;x<31;x++) { -+ if ((1 << x) >= ec->taps) { -+ ec->tappwr = x; -+ break; -+ } -+ } -+ } -+ return ec; -+} -+ -+static inline int echo_can_traintap(echo_can_state_t *ec, int pos, short val) -+{ -+ /* Reset hang counter to avoid adjustments after -+ initial forced training */ -+ ec->hcntr = ec->taps << 1; -+ if (pos >= ec->taps) -+ return 1; -+ ec->a_i[pos] = val << 17; -+ ec->a_s[pos] = val << 1; -+ if (++pos >= ec->taps) -+ return 1; -+ return 0; -+} -+ -+ -+#endif -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec.h mISDN/drivers/isdn/hardware/mISDN/mec.h ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec.h 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/drivers/isdn/hardware/mISDN/mec.h 2005-12-02 09:57:08.000000000 +0100 -@@ -0,0 +1,308 @@ -+/* -+ * Mark's Echo Canceller -+ * -+ * Mark Spencer <markster@linux-support.net> -+ * -+ * Simple, LMS Echo Canceller with double talk detection. -+ * Partly based on the TI App note: -+ * "Digital Voice Echo Canceller with a TMS 32020" -+ * -+ * Special additional thanks to: -+ * Jim Dixon (Lambda Telecommunications) -+ * Iman Ghobrial (Adtran, Inc.) -+ * -+ * Copyright (C) 2001, Linux Support Services, Inc. -+ * -+ * This program is free software and may be used and -+ * distributed according to the terms of the GNU -+ * General Public License, incorporated herein by -+ * reference. -+ * -+ */ -+ -+#ifndef _MEC_H -+#define _MEC_H -+ -+/* You have to express the size of the echo canceller in taps as -+ a power of 2 (6 = 64 taps, 7 = 128 taps, 8 = 256 taps) */ -+#define NUM_TAPS_POW2 6 /* Size of echo canceller in power of 2 (taps) */ -+#define NUM_TAPS (1 << NUM_TAPS_POW2) /* Actual number of taps */ -+#define TAP_MASK (NUM_TAPS-1) -+ -+ -+#define SIGMA_LU_POW NUM_TAPS_POW2 -+#define SIGMA_LY_POW NUM_TAPS_POW2 -+#define SIGMA_YT_POW (NUM_TAPS_POW2 - 1) -+#define SIGMA_ST_POW (NUM_TAPS_POW2 - 1) -+ -+#define BETA_POW 8 -+ -+#define CUTOFF_S 4 -+ -+/* The higher you make this, the better the quality, but the more CPU time required */ -+#define MIN_QUALITY 100 -+ -+/* This optimization saves a lot of processor but may degrade quality */ -+#define OPTIMIZEDIV -+ -+#if 0 -+/* This converges much more slowly but saves processor */ -+#define MIN_UPDATE 256 -+#define MIN_SKIP 8 -+#endif -+ -+#define HANG_T 600 /* 600 samples, or 75ms */ -+ -+typedef struct mark_ec { -+ /* Circular position */ -+ int cpos; -+ short y[NUM_TAPS]; /* Last N samples (relative to cpos) transmitted */ -+ short y_abs[NUM_TAPS]; /* Last N samples (relative to cpos) transmitted (abs value) */ -+ short s[NUM_TAPS]; /* Last N samples (relative to cpos) received */ -+ short s_abs[NUM_TAPS]; /* Last N samples (relative to cpos) received (abs value) */ -+ short u[NUM_TAPS]; /* Last N samples (relative to cpos) with echo removed */ -+ short u_abs[NUM_TAPS]; /* Last N samples (relative to cpos) with echo removed */ -+ -+ int Ly; /* tx power */ -+ int Lu; /* Power of echo-cancelled output */ -+ -+ int Ty[NUM_TAPS]; /* Short term power estimate of transmit */ -+ int Ts; /* Short term power estimate of received signal */ -+ -+ int a[NUM_TAPS]; /* Tap weight coefficients (not relative) */ -+ -+ short sdc[NUM_TAPS]; /* Near end signal before High Pass Filter */ -+ -+ int samples; /* Sample count */ -+ int pass; /* Number of passes we've made */ -+ -+ int hangt; -+ -+ int lastmax; /* Optimize maximum search */ -+ int maxTy; /* Maximum Ty */ -+} echo_can_state_t; -+ -+#define INLINE inline -+ -+#ifdef __KERNEL__ -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#define MALLOC(a) kmalloc((a), GFP_KERNEL) -+#define FREE(a) kfree((a)) -+#else -+#include <stdlib.h> -+#include <unistd.h> -+#include <stdint.h> -+#include <string.h> -+#define MALLOC(a) malloc(a) -+#define FREE(a) free(a) -+#endif -+ -+static INLINE echo_can_state_t *echo_can_create(int len, int adaption_mode) -+{ -+ echo_can_state_t *ec; -+ /* Uhm, we're only one length, sorry. */ -+ ec = MALLOC(sizeof(echo_can_state_t)); -+ if (ec) -+ memset(ec, 0, sizeof(*ec)); -+ return ec; -+} -+ -+#define PASSPOS 32000 -+#undef PASSPOS -+ -+static INLINE void echo_can_free(echo_can_state_t *ec) -+{ -+ FREE(ec); -+} -+ -+static INLINE int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx) -+{ -+ /* Process a sample, where tx is the near end and rx is the far end + echo */ -+ -+ int suppr; -+ int nsuppr; -+ short rxabs, txabs; -+ register int Lu; -+ register int x; -+ register int pos; -+ register int r_hat; /* Estimated echo */ -+ int oldrxabs; -+ int oldtxabs; -+ int oldsupprabs; -+ int supprabs; -+#ifdef MIN_UPDATE -+ int totalupd; -+#endif -+ -+ txabs = abs(tx); -+ rxabs = abs(rx); -+ -+ ec->pass++; -+ -+ r_hat = 0; -+ -+ /* Load next value */ -+ ec->y[ec->cpos] = tx; -+ -+ /* Load next abs value */ -+ oldtxabs = ec->y_abs[ec->cpos]; -+ ec->y_abs[ec->cpos] = txabs; -+ -+ /* Bring in receive value (near-end signal) */ -+ ec->sdc[ec->cpos] = rx; -+ -+ /* Bring in receive value absolute value */ -+ oldrxabs = ec->s_abs[ec->cpos]; -+ ec->s_abs[ec->cpos] = rxabs; -+ -+ Lu = ec->Lu | 1; -+ -+#if 0 -+ /* Apply first order high pass filter (3 dB @ 160 Hz) */ -+ tx = ec->s[ec->cpos] = (1.0-DEFGAMMA) * ec->s[(ec->cpos - 1) & TAP_MASK] + -+ 0.5 * (1.0-DEFGAMMA) * ( ec->sdc[(ec->cpos - 1) & TAP_MASK] - ec->sdc[(ec->cpos - 2) & TAP_MASK]); -+#endif -+ -+ /* Estimate echo */ -+ pos = ec->cpos; -+ for (x=0;x<NUM_TAPS;x++) { -+ r_hat += ec->a[x] * ec->y[pos]; -+ /* Go backwards in time and loop around circular buffer */ -+ pos = (pos - 1) & TAP_MASK; -+ } -+ -+ r_hat >>= 16; -+ -+ if (ec->hangt > 0) -+ ec->hangt--; -+ -+ /* printf("rx: %F, rhat: %F\n", rx, r_hat); */ -+ /* Calculate suppressed amount */ -+ suppr = rx - r_hat; -+ -+ if (ec->pass > NUM_TAPS) { -+ /* Have to have enough taps to start with */ -+ if (ec->maxTy > ec->Ts) { -+ /* There is no near-end speech detected */ -+ if (!ec->hangt) { -+ /* We're not in the hang-time from the end of near-end speech */ -+ if ((ec->Ly > 1024) && ((ec->Ly / Lu) < MIN_QUALITY)) { -+#ifdef OPTIMIZEDIV -+ /* We both have enough signal on the transmit */ -+ nsuppr = (suppr << 18) / ec->Ly; -+ -+ if (nsuppr > 32767) -+ nsuppr = 32767; -+ if (nsuppr < -32768) -+ nsuppr = -32768; -+ -+ nsuppr /= ec->Ly; -+#else -+ /* We both have enough signal on the transmit */ -+ nsuppr = (suppr << 16) / ec->Ly; -+ -+ if (nsuppr > 32767) -+ nsuppr = 32767; -+ if (nsuppr < -32768) -+ nsuppr = -32768; -+ -+#endif -+ -+ /* Update coefficients */ -+ pos = ec->cpos; -+#ifdef MIN_UPDATE -+ totalupd =0; -+#endif -+ for (x=0;x<NUM_TAPS;x++) { -+ register int adj; -+ adj = ec->y[pos] * nsuppr; -+#ifndef OPTIMIZEDIV -+ adj /= ec->Ly; -+ adj >>= BETA_POW; -+#else -+ adj >>= BETA_POW + 2; -+#endif -+#ifdef PASSPOS -+ if (ec->pass > PASSPOS) -+ printf("tx: %d, old %d: %d, adj %d, nsuppr: %d, power: %d\n", tx, x, ec->a[x], adj, nsuppr, ec->Ly); -+#endif -+ ec->a[x] += adj; -+#ifdef MIN_UPDATE -+ totalupd += abs(adj); -+#endif -+ /* Go backwards in time and loop around circular buffer */ -+ pos = (pos - 1) & TAP_MASK; -+ } -+#ifdef MIN_UPDATE -+ /* If we didn't update at least this much, delay for many more taps */ -+ if (totalupd < MIN_UPDATE) { -+ ec->hangt += MIN_SKIP; -+ } -+#endif -+ } -+ -+ } -+ } else -+ /* Near end speech detected */ -+ ec->hangt = HANG_T; -+ } -+ -+ /* Save supression and absolute values */ -+ supprabs = abs(suppr); -+ oldsupprabs = ec->u_abs[ec->cpos]; -+ ec->u[ec->cpos] = suppr; -+ ec->u_abs[ec->cpos] = supprabs; -+ -+ /* Update tx power */ -+ ec->Ly += (txabs >> SIGMA_LY_POW) - (oldtxabs >> SIGMA_LY_POW); -+ -+ /* Update rx power */ -+ ec->Lu += (supprabs >> SIGMA_LU_POW) - (oldsupprabs >> SIGMA_LU_POW); -+ -+ /* Short term power of tx */ -+ ec->Ty[ec->cpos] = ec->Ty[(ec->cpos - 1) & TAP_MASK] + -+ ((txabs >> SIGMA_YT_POW ) - (oldtxabs >> SIGMA_YT_POW)); -+ -+ /* Keep track of highest */ -+ if (ec->lastmax == ec->cpos) { -+ register int maxTy = 0; -+ /* Have to loop through and find the new highest since our old highest expired */ -+ /* Estimate echo */ -+ pos = ec->cpos; -+ for (x=0;x<NUM_TAPS;x++) { -+ if (ec->Ty[pos] > maxTy) -+ maxTy = ec->Ty[pos]; -+ /* Go backwards in time and loop around circular buffer */ -+ pos = (pos - 1) & TAP_MASK; -+ } -+ ec->maxTy = maxTy; -+ } else { -+ /* Just keep the highest */ -+ if (ec->Ty[ec->cpos] > ec->maxTy) { -+ ec->maxTy = ec->Ty[ec->cpos]; -+ ec->lastmax = ec->cpos; -+ } -+ } -+ ec->Ts += (rxabs >> SIGMA_ST_POW) - (oldrxabs >> SIGMA_ST_POW) ; -+ -+ /* Increment position memory */ -+ ec->cpos = (ec->cpos + 1 ) & TAP_MASK; -+ -+ return suppr; -+} -+ -+static inline int echo_can_traintap(echo_can_state_t *ec, int pos, short val) -+{ -+ /* Reset hang counter to avoid adjustments after -+ initial forced training */ -+ ec->hangt = NUM_TAPS << 1; -+ if (pos >= NUM_TAPS) -+ return 1; -+ ec->a[pos] = val << 17; -+ if (++pos >= NUM_TAPS) -+ return 1; -+ return 0; -+} -+ -+#endif -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c 2004-08-27 21:27:40.000000000 +0200 -+++ mISDN/drivers/isdn/hardware/mISDN/sedl_fax.c 2005-12-02 09:57:08.000000000 +0100 -@@ -811,8 +811,8 @@ - return(err); - } - -- printk(KERN_INFO "mISDN: sedlpci found adapter %s at %s\n", -- (char *) ent->driver_data, pdev->slot_name); -+/* printk(KERN_INFO "mISDN: sedlpci found adapter %s at %s\n", -+ (char *) ent->driver_data, pdev->slot_name); */ - - card->cfg = pci_resource_start(pdev, 0); - card->irq = pdev->irq; -diff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/w6692.c mISDN/drivers/isdn/hardware/mISDN/w6692.c ---- /tmp/mISDN/drivers/isdn/hardware/mISDN/w6692.c 2004-08-27 21:27:40.000000000 +0200 -+++ mISDN/drivers/isdn/hardware/mISDN/w6692.c 2005-12-02 09:57:08.000000000 +0100 -@@ -1502,8 +1502,8 @@ - return(err); - } - -- printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n", -- (char *) ent->driver_data, pdev->slot_name); -+/* printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n", -+ (char *) ent->driver_data, pdev->slot_name); */ - - card->addr = pci_resource_start(pdev, 1); - card->irq = pdev->irq; -diff -u -r -P /tmp/mISDN/include/linux/mISDNif.h mISDN/include/linux/mISDNif.h ---- /tmp/mISDN/include/linux/mISDNif.h 2005-02-05 11:18:17.000000000 +0100 -+++ mISDN/include/linux/mISDNif.h 2005-12-02 09:57:08.000000000 +0100 -@@ -173,6 +173,8 @@ - #define BF_DISABLE 0x2315 - #define BF_ACCEPT 0x2316 - #define BF_REJECT 0x2317 -+#define ECHOCAN_ON 0x2318 -+#define ECHOCAN_OFF 0x2319 - #define HW_POTS_ON 0x1001 - #define HW_POTS_OFF 0x1002 - #define HW_POTS_SETMICVOL 0x1100 -diff -u -r -P /tmp/mISDN/Makefile mISDN/Makefile ---- /tmp/mISDN/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ mISDN/Makefile 2005-12-05 19:08:57.000000000 +0100 -@@ -0,0 +1,54 @@ -+BASEDIR=$(shell pwd) -+ -+ -+INSTALL_PREFIX := / -+export INSTALL_PREFIX -+ -+#PATH to linux source/headers -+#LINUX=/usr/src/linux -+LINUX=/lib/modules/$(shell uname -r)/build -+ -+MISDNDIR=$(BASEDIR) -+MISDN_SRC=$(MISDNDIR)/drivers/isdn/hardware/mISDN -+ -+######################################## -+# USER CONFIGS END -+######################################## -+ -+CONFIGS+=CONFIG_MISDN_DRV=m CONFIG_MISDN_DSP=m -+CONFIGS+=CONFIG_MISDN_HFCMULTI=m -+CONFIGS+=CONFIG_MISDN_HFCPCI=m -+CONFIGS+=CONFIG_MISDN_HFCUSB=m -+#CONFIGS+=CONFIG_MISDN_AVM_FRITZ=m -+ -+ -+MINCLUDES+=-I$(MISDNDIR)/include -+ -+all: -+ @echo -+ @echo "Makeing mISDN" -+ @echo "=============" -+ @echo -+ cp $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile.v2.6 $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile -+ -+ cd $(LINUX) ; make SUBDIRS=$(MISDN_SRC) modules $(CONFIGS) LINUXINCLUDE="$(MINCLUDES) -I$(LINUX)/include" -+ -+ -+ -+install: all -+ cd $(LINUX) ; make SUBDIRS=$(MISDN_SRC) modules_install -+ cp $(MISDNDIR)/include/linux/*.h $(INSTALL_PREFIX)/usr/include/linux/ -+ depmod -+ -+.PHONY: install all clean -+ -+clean: -+ rm -rf drivers/isdn/hardware/mISDN/*.o -+ rm -rf drivers/isdn/hardware/mISDN/*.ko -+ rm -rf *~ -+ find . -iname ".*.cmd" -exec rm -rf {} \; -+ find . -iname ".*.d" -exec rm -rf {} \; -+ find . -iname "*.mod.c" -exec rm -rf {} \; -+ find . -iname "*.mod" -exec rm -rf {} \; -+ -+ diff --git a/channels/misdn/portinfo.c b/channels/misdn/portinfo.c deleted file mode 100644 index c7add95fb..000000000 --- a/channels/misdn/portinfo.c +++ /dev/null @@ -1,197 +0,0 @@ - - -#include "isdn_lib.h" - - -/* - * global function to show all available isdn ports - */ -void isdn_port_info(void) -{ - int err; - int i, ii, p; - int useable, nt, pri; - unsigned char buff[1025]; - iframe_t *frm = (iframe_t *)buff; - stack_info_t *stinf; - int device; - - /* open mISDN */ - if ((device = mISDN_open()) < 0) - { - fprintf(stderr, "mISDN_open() failed: ret=%d errno=%d (%s) Check for mISDN modules and device.\n", device, errno, strerror(errno)); - exit(-1); - } - - /* get number of stacks */ - i = 1; - ii = mISDN_get_stack_count(device); - printf("\n"); - if (ii <= 0) - { - printf("Found no card. Please be sure to load card drivers.\n"); - } - - /* loop the number of cards and get their info */ - while(i <= ii) - { - err = mISDN_get_stack_info(device, i, buff, sizeof(buff)); - if (err <= 0) - { - fprintf(stderr, "mISDN_get_stack_info() failed: port=%d err=%d\n", i, err); - break; - } - stinf = (stack_info_t *)&frm->data.p; - - nt = pri = 0; - useable = 1; - - /* output the port info */ - printf("Port %2d: ", i); - switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK) - { - case ISDN_PID_L0_TE_S0: - printf("TE-mode BRI S/T interface line (for phone lines)"); -#if 0 - if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_S0_HFC & ISDN_PID_FEATURE_MASK) - printf(" HFC multiport card"); -#endif - break; - case ISDN_PID_L0_NT_S0: - nt = 1; - printf("NT-mode BRI S/T interface port (for phones)"); -#if 0 - if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_S0_HFC & ISDN_PID_FEATURE_MASK) - printf(" HFC multiport card"); -#endif - break; - case ISDN_PID_L0_TE_U: - printf("TE-mode BRI U interface line"); - break; - case ISDN_PID_L0_NT_U: - nt = 1; - printf("NT-mode BRI U interface port"); - break; - case ISDN_PID_L0_TE_UP2: - printf("TE-mode BRI Up2 interface line"); - break; - case ISDN_PID_L0_NT_UP2: - nt = 1; - printf("NT-mode BRI Up2 interface port"); - break; - case ISDN_PID_L0_TE_E1: - pri = 1; - printf("TE-mode PRI E1 interface line (for phone lines)"); -#if 0 - if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_E1_HFC & ISDN_PID_FEATURE_MASK) - printf(" HFC-E1 card"); -#endif - break; - case ISDN_PID_L0_NT_E1: - nt = 1; - pri = 1; - printf("NT-mode PRI E1 interface port (for phones)"); -#if 0 - if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_E1_HFC & ISDN_PID_FEATURE_MASK) - printf(" HFC-E1 card"); -#endif - break; - default: - useable = 0; - printf("unknown type 0x%08x",stinf->pid.protocol[0]); - } - printf("\n"); - - if (nt) - { - if (stinf->pid.protocol[1] == 0) - { - useable = 0; - printf(" -> Missing layer 1 NT-mode protocol.\n"); - } - p = 2; - while(p <= MAX_LAYER_NR) { - if (stinf->pid.protocol[p]) - { - useable = 0; - printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for NT lib.\n", p, stinf->pid.protocol[p]); - } - p++; - } - if (useable) - { - if (pri) - printf(" -> Interface is Point-To-Point (PRI).\n"); - else - printf(" -> Interface can be Poin-To-Point/Multipoint.\n"); - } - } else - { - if (stinf->pid.protocol[1] == 0) - { - useable = 0; - printf(" -> Missing layer 1 protocol.\n"); - } - if (stinf->pid.protocol[2] == 0) - { - useable = 0; - printf(" -> Missing layer 2 protocol.\n"); - } - if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP) - { - printf(" -> Interface is Poin-To-Point.\n"); - } - if (stinf->pid.protocol[3] == 0) - { - useable = 0; - printf(" -> Missing layer 3 protocol.\n"); - } else - { - printf(" -> Protocol: "); - switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK) - { - case ISDN_PID_L3_DSS1USER: - printf("DSS1 (Euro ISDN)"); - break; - - default: - useable = 0; - printf("unknown protocol 0x%08x",stinf->pid.protocol[3]); - } - printf("\n"); - } - p = 4; - while(p <= MAX_LAYER_NR) { - if (stinf->pid.protocol[p]) - { - useable = 0; - printf(" -> Layer %d protocol 0x%08x is detected, but not allowed for TE lib.\n", p, stinf->pid.protocol[p]); - } - p++; - } - printf(" -> childcnt: %d\n",stinf->childcnt); - } - - if (!useable) - printf(" * Port NOT useable for PBX\n"); - - printf("--------\n"); - - i++; - } - printf("\n"); - - /* close mISDN */ - if ((err = mISDN_close(device))) - { - fprintf(stderr, "mISDN_close() failed: err=%d '%s'\n", err, strerror(err)); - exit(-1); - } -} - - -int main() -{ - isdn_port_info(); - return 0; -} |