aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorroot <root@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-17 22:04:22 +0000
committerroot <root@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-17 22:04:22 +0000
commitb1742b89db7d0f0335f59a3b701895683e0f3d2f (patch)
tree4a433ea2f38280b587e2d14eb297ea95d2d710dd /channels
parent62245abb42c1e23df30e8bb1b80920750fcfc7b6 (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')
-rw-r--r--channels/Makefile18
-rw-r--r--channels/chan_misdn.c3227
-rw-r--r--channels/chan_misdn_config.c1083
-rw-r--r--channels/misdn/Makefile58
-rw-r--r--channels/misdn/chan_misdn_config.h29
-rw-r--r--channels/misdn/fac.c313
-rw-r--r--channels/misdn/fac.h8
-rw-r--r--channels/misdn/ie.c353
-rw-r--r--channels/misdn/isdn_lib.c2791
-rw-r--r--channels/misdn/isdn_lib.h175
-rw-r--r--channels/misdn/isdn_lib_intern.h24
-rw-r--r--channels/misdn/isdn_msg_parser.c384
-rw-r--r--channels/misdn/mISDN.patch2500
-rw-r--r--channels/misdn/portinfo.c197
-rw-r--r--channels/misdn_config.c784
15 files changed, 5455 insertions, 6489 deletions
diff --git a/channels/Makefile b/channels/Makefile
index 10ff8c128..3a02cf3bd 100644
--- a/channels/Makefile
+++ b/channels/Makefile
@@ -81,9 +81,9 @@ ifneq ($(wildcard h323/libchanh323.a),)
CHANNEL_LIBS+=chan_h323.so
endif
-ifneq ($(wildcard misdn/chan_misdn_lib.a),)
+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/mISDNuser/mISDNlib.h),)
CHANNEL_LIBS+=chan_misdn.so
- CFLAGS+=-Imisdn
+ CFLAGS+=-Imisdn
endif
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
@@ -239,11 +239,17 @@ chan_h323.so: chan_h323.o h323/libchanh323.a
$(CC) $(SOLINK) -o $@ $< h323/libchanh323.a $(CHANH323LIB) -L$(PWLIBDIR)/lib $(PTLIB) -L$(OPENH323DIR)/lib $(H323LIB) -L/usr/lib -lcrypto -lssl -lexpat
endif
-chan_misdn.so: chan_misdn.o chan_misdn_config.o misdn/chan_misdn_lib.a
- $(CC) -shared -Xlinker -x -L/usr/lib -o $@ $^ -lmISDN -lisdnnet
+misdn/chan_misdn_lib.a:
+ make -C misdn
-chan_misdn.o: chan_misdn.c
- $(CC) $(CFLAGS) -DCHAN_MISDN_VERSION=\"0.2.1\" -c $< -o $@
+chan_misdn.so: chan_misdn.o misdn_config.o misdn/chan_misdn_lib.a
+ $(CC) -shared -Xlinker -x -L/usr/lib -o $@ $^ -lisdnnet -lmISDN
+
+chan_misdn.o: chan_misdn.c
+ $(CC) $(CFLAGS) -DCHAN_MISDN_VERSION=\"0.3.0\" -c $< -o $@
+
+misdn_config.o: misdn_config.c misdn/chan_misdn_config.h
+ $(CC) $(CFLAGS) -DCHAN_MISDN_VERSION=\"0.3.0\" -c $< -o $@
#chan_modem.so : chan_modem.o
# $(CC) -rdynamic -shared -Xlinker -x -o $@ $<
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index a170105ff..5b322f6bf 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -59,28 +59,63 @@
#include <asterisk/app.h>
#include <asterisk/features.h>
-#include "chan_misdn_config.h"
-#include "isdn_lib.h"
+#include <chan_misdn_config.h>
+#include <isdn_lib.h>
+
+char global_tracefile[BUFFERSIZE+1];
+
+
+struct misdn_jb{
+ int size;
+ int upper_threshold;
+ char *samples, *ok;
+ int wp,rp;
+ int state_empty;
+ int state_full;
+ int state_buffer;
+ int bytes_wrote;
+ ast_mutex_t mutexjb;
+};
+
+
+
+/* allocates the jb-structure and initialise the elements*/
+struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
+
+/* frees the data and destroys the given jitterbuffer struct */
+void misdn_jb_destroy(struct misdn_jb *jb);
+
+/* fills the jitterbuffer with len data returns < 0 if there was an
+error (bufferoverun). */
+int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
+
+/* gets len bytes out of the jitterbuffer if available, else only the
+available data is returned and the return value indicates the number
+of data. */
+int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
-ast_mutex_t release_lock_mutex;
-#define release_lock ast_mutex_lock(&release_lock_mutex)
-#define release_unlock ast_mutex_unlock(&release_lock_mutex)
/* BEGIN: chan_misdn.h */
+
+
enum misdn_chan_state {
MISDN_NOTHING, /*!< at beginning */
MISDN_WAITING4DIGS, /*!< when waiting for infos */
MISDN_EXTCANTMATCH, /*!< when asterisk couldnt match our ext */
MISDN_DIALING, /*!< when pbx_start */
MISDN_PROGRESS, /*!< we got a progress */
+ MISDN_PROCEEDING, /*!< we got a progress */
MISDN_CALLING, /*!< when misdn_call is called */
MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
MISDN_ALERTING, /*!< when Alerting */
MISDN_BUSY, /*!< when BUSY */
MISDN_CONNECTED, /*!< when connected */
+ MISDN_PRECONNECTED, /*!< when connected */
+ MISDN_DISCONNECTED, /*!< when connected */
+ MISDN_RELEASED, /*!< when connected */
MISDN_BRIDGED, /*!< when bridged */
MISDN_CLEANING, /*!< when hangup from * but we were connected before */
MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP cam from misdn */
@@ -98,13 +133,24 @@ struct chan_list {
ast_mutex_t lock;
+ char allowed_bearers[BUFFERSIZE+1];
+
enum misdn_chan_state state;
- int holded;
+ int need_queue_hangup;
+ int need_hangup;
+ int need_busy;
+
int orginator;
int norxtone;
int notxtone;
+ int toggle_ec;
+
+ int incoming_early_audio;
+
+ int ignore_dtmf;
+
int pipe[2];
char ast_rd_buf[4096];
struct ast_frame frame;
@@ -113,17 +159,34 @@ struct chan_list {
int faxhandled;
int ast_dsp;
+
+ int jb_len;
+ int jb_upper_threshold;
+ struct misdn_jb *jb;
struct ast_dsp *dsp;
struct ast_trans_pvt *trans;
struct ast_channel * ast;
+
+ int dummy;
struct misdn_bchannel *bc;
struct misdn_bchannel *holded_bc;
unsigned int l3id;
int addr;
+
+ char context[BUFFERSIZE];
+
+ int zero_read_cnt;
+ int dropped_frame_cnt;
+
+ int far_alerting;
+ int other_pid;
+ struct chan_list *other_ch;
+
+ const struct tone_zone_sound *ts;
struct chan_list *peer;
struct chan_list *next;
@@ -131,6 +194,11 @@ struct chan_list {
struct chan_list *first;
};
+
+
+void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
+void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
+
struct robin_list {
char *group;
int port;
@@ -140,13 +208,19 @@ struct robin_list {
};
static struct robin_list *robin = NULL;
+
+
+struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
+
+
+
static inline void free_robin_list_r (struct robin_list *r)
{
- if (r) {
- if (r->next) free_robin_list_r(r->next);
- if (r->group) free(r->group);
- free(r);
- }
+ if (r) {
+ if (r->next) free_robin_list_r(r->next);
+ if (r->group) free(r->group);
+ free(r);
+ }
}
static void free_robin_list ( void )
@@ -155,7 +229,7 @@ static void free_robin_list ( void )
robin = NULL;
}
-struct robin_list* get_robin_position (char *group)
+static struct robin_list* get_robin_position (char *group)
{
struct robin_list *iter = robin;
for (; iter; iter = iter->next) {
@@ -173,8 +247,11 @@ struct robin_list* get_robin_position (char *group)
return robin;
}
-struct ast_channel *misdn_new(struct chan_list *cl, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c);
-void send_digit_to_chan(struct chan_list *cl, char digit );
+
+static void chan_misdn_log(int level, int port, char *tmpl, ...);
+
+static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
+static void send_digit_to_chan(struct chan_list *cl, char digit );
#define AST_CID_P(ast) ast->cid.cid_num
@@ -184,48 +261,50 @@ void send_digit_to_chan(struct chan_list *cl, char digit );
#define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
#define MISDN_ASTERISK_PVT(ast) 1
-#define MISDN_ASTERISK_TYPE(ast) ast->tech->type
-
-/* END: chan_misdn.h */
#include <asterisk/strings.h>
/* #define MISDN_DEBUG 1 */
-static char *desc = "Channel driver for mISDN Support (Bri/Pri)";
-static char *type = "mISDN";
+static char *desc = "Channel driver for mISDN Support (Bri/Pri)";
+static const char misdn_type[] = "mISDN";
-int tracing = 0 ;
+static int tracing = 0 ;
static int usecnt=0;
-char **misdn_key_vector=NULL;
-int misdn_key_vector_size=0;
+static char **misdn_key_vector=NULL;
+static int misdn_key_vector_size=0;
/* Only alaw and mulaw is allowed for now */
static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
static ast_mutex_t usecnt_lock;
-int *misdn_debug;
-int *misdn_debug_only;
-int max_ports;
+static int *misdn_debug;
+static int *misdn_debug_only;
+static int max_ports;
struct chan_list dummy_cl;
struct chan_list *cl_te=NULL;
ast_mutex_t cl_te_lock;
-enum event_response_e
+static enum event_response_e
cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
-void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc);
+static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
+
+static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
+static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
+static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
+static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
-void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
-void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
-struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
-void chan_misdn_log(int level, int port, char *tmpl, ...);
-void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...);
+
+
+static int dialtone_indicate(struct chan_list *cl);
+static int hanguptone_indicate(struct chan_list *cl);
+static int stop_indicate(struct chan_list *cl);
static int start_bc_tones(struct chan_list *cl);
static int stop_bc_tones(struct chan_list *cl);
@@ -234,6 +313,10 @@ static void release_chan(struct misdn_bchannel *bc);
static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
static int misdn_facility_exec(struct ast_channel *chan, void *data);
+int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
+
+static int update_ec_config(struct misdn_bchannel *bc);
+
/*************** Helpers *****************/
static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
@@ -258,25 +341,21 @@ static struct chan_list * get_chan_by_ast_name(char *name)
return NULL;
}
-static char* tone2str(struct misdn_bchannel *bc)
-{
- static struct {
- char name[16];
- enum tone_e tone;
- } *tone, tone_buf[] = {
- {"NOTONE",TONE_NONE},
- {"DIAL",TONE_DIAL},
- {"BUSY",TONE_BUSY},
- {"ALERT",TONE_ALERTING},
- {"",TONE_NONE}
- };
-
-
- for (tone=&tone_buf[0]; tone->name[0]; tone++) {
- if (tone->tone == bc->tone) return tone->name;
- }
- return NULL;
-}
+
+
+struct allowed_bearers {
+ int cap;
+ int val;
+ char *name;
+};
+
+struct allowed_bearers allowed_bearers_array[]={
+ {INFO_CAPABILITY_SPEECH,1,"speech"},
+ {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
+ {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
+ {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"},
+ {INFO_CAPABILITY_VIDEO,16,"video"}
+};
static char *bearer2str(int cap) {
static char *bearers[]={
@@ -284,6 +363,7 @@ static char *bearer2str(int cap) {
"Audio 3.1k",
"Unres Digital",
"Res Digital",
+ "Video",
"Unknown Bearer"
};
@@ -300,9 +380,30 @@ static char *bearer2str(int cap) {
case INFO_CAPABILITY_DIGITAL_RESTRICTED:
return bearers[3];
break;
- default:
+ case INFO_CAPABILITY_VIDEO:
return bearers[4];
break;
+ default:
+ return bearers[5];
+ break;
+ }
+}
+
+
+static void print_facility( struct misdn_bchannel *bc)
+{
+ switch (bc->fac_type) {
+ case FACILITY_CALLDEFLECT:
+ chan_misdn_log(2,bc->port," --> calldeflect: %s\n",
+ bc->fac.calldeflect_nr);
+ break;
+ case FACILITY_CENTREX:
+ chan_misdn_log(2,bc->port," --> centrex: %s\n",
+ bc->fac.cnip);
+ break;
+ default:
+ chan_misdn_log(2,bc->port," --> unknown\n");
+
}
}
@@ -322,7 +423,7 @@ static void print_bearer(struct misdn_bchannel *bc)
}
/*************** Helpers END *************/
-void send_digit_to_chan(struct chan_list *cl, char digit )
+static void send_digit_to_chan(struct chan_list *cl, char digit )
{
static const char* dtmf_tones[] = {
"!941+1336/100,!0/100", /* 0 */
@@ -416,10 +517,38 @@ static int misdn_set_debug(int fd, int argc, char *argv[])
return 0;
}
-
static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
{
- if (argc != 5 )return RESULT_SHOWUSAGE;
+ if (argc != 5) return RESULT_SHOWUSAGE;
+
+ return 0;
+}
+
+
+static int misdn_port_block(int fd, int argc, char *argv[])
+{
+ int port;
+
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+
+ port = atoi(argv[3]);
+
+ misdn_lib_port_block(port);
+
+ return 0;
+}
+
+static int misdn_port_unblock(int fd, int argc, char *argv[])
+{
+ int port;
+
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+
+ port = atoi(argv[3]);
+
+ misdn_lib_port_unblock(port);
return 0;
}
@@ -453,6 +582,20 @@ static int misdn_port_up (int fd, int argc, char *argv[])
return 0;
}
+static int misdn_port_down (int fd, int argc, char *argv[])
+{
+ int port;
+
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+
+ port = atoi(argv[3]);
+
+ misdn_lib_get_port_down(port);
+
+ return 0;
+}
+
static int misdn_show_config (int fd, int argc, char *argv[])
{
@@ -470,12 +613,12 @@ static int misdn_show_config (int fd, int argc, char *argv[])
if (argc == 3 || onlyport == 0) {
ast_cli(fd,"Misdn General-Config: \n");
- ast_cli(fd," -> VERSION: " CHAN_MISDN_VERSION "\n");
-
+ ast_cli(fd," -> Version: chan_misdn-" CHAN_MISDN_VERSION "\n");
for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
}
+ ast_cli(fd, "\n");
}
if (onlyport < 0) {
@@ -505,23 +648,26 @@ static int misdn_show_config (int fd, int argc, char *argv[])
return 0;
}
-
-
struct state_struct {
enum misdn_chan_state state;
char txt[255] ;
} ;
-struct state_struct state_array[] = {
+static struct state_struct state_array[] = {
{MISDN_NOTHING,"NOTHING"}, /* at beginning */
{MISDN_WAITING4DIGS,"WAITING4DIGS"}, /* when waiting for infos */
{MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /* when asterisk couldnt match our ext */
{MISDN_DIALING,"DIALING"}, /* when pbx_start */
{MISDN_PROGRESS,"PROGRESS"}, /* when pbx_start */
+ {MISDN_PROCEEDING,"PROCEEDING"}, /* when pbx_start */
{MISDN_CALLING,"CALLING"}, /* when misdn_call is called */
+ {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
{MISDN_ALERTING,"ALERTING"}, /* when Alerting */
{MISDN_BUSY,"BUSY"}, /* when BUSY */
{MISDN_CONNECTED,"CONNECTED"}, /* when connected */
+ {MISDN_PRECONNECTED,"PRECONNECTED"}, /* when connected */
+ {MISDN_DISCONNECTED,"DISCONNECTED"}, /* when connected */
+ {MISDN_RELEASED,"RELEASED"}, /* when connected */
{MISDN_BRIDGED,"BRIDGED"}, /* when bridged */
{MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
{MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
@@ -531,45 +677,44 @@ struct state_struct state_array[] = {
/* misdn_hangup */
};
-
-
-
-char *misdn_get_ch_state(struct chan_list *p)
+static char *misdn_get_ch_state(struct chan_list *p)
{
int i;
+ static char state[8];
+
if( !p) return NULL;
for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
if ( state_array[i].state == p->state) return state_array[i].txt;
}
-
- return NULL;
+
+ sprintf(state,"%d",p->state) ;
+
+ return state;
}
-static int misdn_reload (int fd, int argc, char *argv[])
+
+
+void reload_config(void)
{
int i, cfg_debug;
- ast_cli(fd, "Reloading mISDN Config\n");
- chan_misdn_log(0, 0, "Dynamic Crypting Activation is not support during reload at the moment\n");
-
free_robin_list();
-
misdn_cfg_reload();
-
- {
- char tempbuf[BUFFERSIZE];
- misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
- if (strlen(tempbuf))
- tracing = 1;
- }
-
+ misdn_cfg_update_ptp();
+ misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
+
for (i = 0; i <= max_ports; i++) {
misdn_debug[i] = cfg_debug;
misdn_debug_only[i] = 0;
}
-
+}
+
+static int misdn_reload (int fd, int argc, char *argv[])
+{
+ ast_cli(fd, "Reloading mISDN Config\n");
+ reload_config();
return 0;
}
@@ -577,12 +722,14 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
{
struct ast_channel *ast=help->ast;
ast_cli(fd,
- "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s ctx:%s state:%s\n",
+ "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
+
bc->pid, bc->port, bc->channel,
bc->nt?"NT":"TE",
help->orginator == ORG_AST?"*":"I",
ast?ast->exten:NULL,
ast?AST_CID_P(ast):NULL,
+ bc->rad,
ast?ast->context:NULL,
misdn_get_ch_state(help)
);
@@ -593,9 +740,9 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
" --> ch_addr: %x\n"
" --> bc_addr: %x\n"
" --> bc_l3id: %x\n"
- " --> tone: %s\n"
" --> display: %s\n"
" --> activated: %d\n"
+ " --> state: %s\n"
" --> capability: %s\n"
" --> echo_cancel: %d\n"
" --> notone : rx %d tx:%d\n"
@@ -605,19 +752,19 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
help->addr,
bc->addr,
bc?bc->l3_id:-1,
- tone2str(bc),
bc->display,
bc->active,
+ bc_state2str(bc->bc_state),
bearer2str(bc->capability),
bc->ec_enable,
+
help->norxtone,help->notxtone,
bc->holded, help->holded_bc?1:0
);
}
-
static int misdn_show_cls (int fd, int argc, char *argv[])
{
struct chan_list *help=cl_te;
@@ -642,8 +789,6 @@ static int misdn_show_cls (int fd, int argc, char *argv[])
return 0;
}
-
-
static int misdn_show_cl (int fd, int argc, char *argv[])
{
struct chan_list *help=cl_te;
@@ -680,13 +825,12 @@ static int misdn_set_tics (int fd, int argc, char *argv[])
return 0;
}
-
-
static int misdn_show_stacks (int fd, int argc, char *argv[])
{
int port;
-
+
ast_cli(fd, "BEGIN STACK_LIST:\n");
+
for (port=misdn_cfg_get_next_port(0); port > 0;
port=misdn_cfg_get_next_port(port)) {
char buf[128];
@@ -746,8 +890,6 @@ static int misdn_send_cd (int fd, int argc, char *argv[])
return 0;
}
-
-
static int misdn_send_digit (int fd, int argc, char *argv[])
{
char *channame;
@@ -806,9 +948,11 @@ static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
return 0;
} else {
- tmp->bc->ec_enable=tmp->bc->ec_enable?0:1;
+
+ tmp->toggle_ec=tmp->toggle_ec?0:1;
- if (tmp->bc->ec_enable) {
+ if (tmp->toggle_ec) {
+ update_ec_config(tmp->bc);
manager_ec_enable(tmp->bc);
} else {
manager_ec_disable(tmp->bc);
@@ -819,8 +963,6 @@ static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
return 0;
}
-
-
static int misdn_send_display (int fd, int argc, char *argv[])
{
char *channame;
@@ -838,9 +980,7 @@ static int misdn_send_display (int fd, int argc, char *argv[])
tmp=get_chan_by_ast_name(channame);
if (tmp && tmp->bc) {
- int l = sizeof(tmp->bc->display);
- strncpy(tmp->bc->display, msg, l);
- tmp->bc->display[l-1] = 0;
+ ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
} else {
ast_cli(fd,"No such channel %s\n",channame);
@@ -851,9 +991,6 @@ static int misdn_send_display (int fd, int argc, char *argv[])
return RESULT_SUCCESS ;
}
-
-
-
static char *complete_ch_helper(char *line, char *word, int pos, int state, int rpos)
{
struct ast_channel *c;
@@ -909,7 +1046,6 @@ static struct ast_cli_entry cli_send_cd =
complete_ch
};
-
static struct ast_cli_entry cli_send_digit =
{ {"misdn","send","digit", NULL},
misdn_send_digit,
@@ -920,7 +1056,6 @@ static struct ast_cli_entry cli_send_digit =
complete_ch
};
-
static struct ast_cli_entry cli_toggle_echocancel =
{ {"misdn","toggle","echocancel", NULL},
misdn_toggle_echocancel,
@@ -929,8 +1064,6 @@ static struct ast_cli_entry cli_toggle_echocancel =
complete_ch
};
-
-
static struct ast_cli_entry cli_send_display =
{ {"misdn","send","display", NULL},
misdn_send_display,
@@ -941,7 +1074,6 @@ static struct ast_cli_entry cli_send_display =
complete_ch
};
-
static struct ast_cli_entry cli_show_config =
{ {"misdn","show","config", NULL},
misdn_show_config,
@@ -949,7 +1081,6 @@ static struct ast_cli_entry cli_show_config =
"Usage: misdn show config [port | 0]\n use 0 to only print the general config.\n"
};
-
static struct ast_cli_entry cli_reload =
{ {"misdn","reload", NULL},
misdn_reload,
@@ -964,7 +1095,6 @@ static struct ast_cli_entry cli_set_tics =
"\n"
};
-
static struct ast_cli_entry cli_show_cls =
{ {"misdn","show","channels", NULL},
misdn_show_cls,
@@ -980,6 +1110,19 @@ static struct ast_cli_entry cli_show_cl =
complete_ch
};
+static struct ast_cli_entry cli_port_block=
+{ {"misdn","port","block", NULL},
+ misdn_port_block,
+ "Blocks the given port",
+ "Usage: misdn port block\n"
+};
+
+static struct ast_cli_entry cli_port_unblock=
+{ {"misdn","port","unblock", NULL},
+ misdn_port_unblock,
+ "Unblocks the given port",
+ "Usage: misdn port unblock\n"
+};
static struct ast_cli_entry cli_restart_port =
@@ -989,7 +1132,6 @@ static struct ast_cli_entry cli_restart_port =
"Usage: misdn restart port\n"
};
-
static struct ast_cli_entry cli_port_up =
{ {"misdn","port","up", NULL},
misdn_port_up,
@@ -997,6 +1139,14 @@ static struct ast_cli_entry cli_port_up =
"Usage: misdn port up <port>\n"
};
+static struct ast_cli_entry cli_port_down =
+{ {"misdn","port","down", NULL},
+ misdn_port_down,
+ "Tries to deacivate the L1 on the given port",
+ "Usage: misdn port down <port>\n"
+};
+
+
static struct ast_cli_entry cli_show_stacks =
{ {"misdn","show","stacks", NULL},
@@ -1012,8 +1162,6 @@ static struct ast_cli_entry cli_show_port =
"Usage: misdn show port <port>\n"
};
-
-
static struct ast_cli_entry cli_set_debug =
{ {"misdn","set","debug", NULL},
misdn_set_debug,
@@ -1031,6 +1179,372 @@ static struct ast_cli_entry cli_set_crypt_debug =
/*** CLI END ***/
+static int update_config (struct chan_list *ch, int orig)
+{
+ if (!ch) {
+ ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
+ return -1;
+ }
+
+ struct ast_channel *ast=ch->ast;
+ struct misdn_bchannel *bc=ch->bc;
+ if (! ast || ! bc ) {
+ ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
+ return -1;
+ }
+
+ int port=bc->port;
+
+ chan_misdn_log(1,port,"update_config: Getting Config\n");
+
+
+ int hdlc=0;
+ misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
+
+ if (hdlc) {
+ switch (bc->capability) {
+ case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
+ case INFO_CAPABILITY_DIGITAL_RESTRICTED:
+ chan_misdn_log(1,bc->port," --> CONF HDLC\n");
+ bc->hdlc=1;
+ break;
+ }
+
+ }
+
+
+ int pres, screen;
+
+ misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
+ chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
+
+ if ( (pres + screen) < 0 ) {
+
+ chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
+
+ switch (ast->cid.cid_pres & 0x60){
+
+ case AST_PRES_RESTRICTED:
+ bc->pres=1;
+ chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
+ break;
+
+
+ case AST_PRES_UNAVAILABLE:
+ bc->pres=2;
+ chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
+ break;
+
+ default:
+ bc->pres=0;
+ chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
+ }
+
+ switch (ast->cid.cid_pres & 0x3){
+
+ case AST_PRES_USER_NUMBER_UNSCREENED:
+ bc->screen=0;
+ chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
+ break;
+
+ case AST_PRES_USER_NUMBER_PASSED_SCREEN:
+ bc->screen=1;
+ chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
+ break;
+ case AST_PRES_USER_NUMBER_FAILED_SCREEN:
+ bc->screen=2;
+ chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
+ break;
+
+ case AST_PRES_NETWORK_NUMBER:
+ bc->screen=3;
+ chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
+ break;
+
+ default:
+ bc->screen=0;
+ chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
+ }
+
+
+ } else {
+ bc->screen=screen;
+ bc->pres=pres;
+ }
+
+ return 0;
+
+}
+
+
+
+
+void config_jitterbuffer(struct chan_list *ch)
+{
+ struct misdn_bchannel *bc=ch->bc;
+ int len=ch->jb_len, threshold=ch->jb_upper_threshold;
+
+ chan_misdn_log(5,bc->port, "config_jb: Called\n");
+
+ if ( ! len ) {
+ chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
+ bc->nojitter=1;
+ } else {
+
+ if (len <=100 || len > 8000) {
+ chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
+ len=1000;
+ }
+
+ if ( threshold > len ) {
+ chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
+ }
+
+ if ( ch->jb) {
+ cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
+ misdn_jb_destroy(ch->jb);
+ ch->jb=NULL;
+ }
+
+ ch->jb=misdn_jb_init(len, threshold);
+
+ if (!ch->jb )
+ bc->nojitter=1;
+ }
+}
+
+
+void debug_numplan(int port, int numplan, char *type)
+{
+ switch (numplan) {
+ case NUMPLAN_INTERNATIONAL:
+ chan_misdn_log(2, port, " --> %s: International\n",type);
+ break;
+ case NUMPLAN_NATIONAL:
+ chan_misdn_log(2, port, " --> %s: National\n",type);
+ break;
+ case NUMPLAN_SUBSCRIBER:
+ chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
+ break;
+ case NUMPLAN_UNKNOWN:
+ chan_misdn_log(2, port, " --> %s: Unknown\n",type);
+ break;
+ /* Maybe we should cut off the prefix if present ? */
+ default:
+ chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
+ break;
+ }
+}
+
+
+
+
+static int update_ec_config(struct misdn_bchannel *bc)
+{
+ int ec;
+ int port=bc->port;
+
+ misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+
+ if (ec == 1 ) {
+ bc->ec_enable=1;
+ } else if ( ec > 1 ) {
+ bc->ec_enable=1;
+ bc->ec_deftaps=ec;
+ }
+
+ return 0;
+}
+
+
+static int read_config(struct chan_list *ch, int orig) {
+
+ if (!ch) {
+ ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
+ return -1;
+ }
+
+ struct ast_channel *ast=ch->ast;
+ struct misdn_bchannel *bc=ch->bc;
+ if (! ast || ! bc ) {
+ ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
+ return -1;
+ }
+
+ int port=bc->port;
+
+ chan_misdn_log(5,port,"read_config: Getting Config\n");
+
+ char lang[BUFFERSIZE+1];
+
+ misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
+ ast_copy_string(ast->language, lang, sizeof(ast->language));
+
+ char musicclass[BUFFERSIZE+1];
+
+ misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, musicclass, BUFFERSIZE);
+ ast_copy_string(ast->musicclass, musicclass, sizeof(ast->musicclass));
+
+ misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
+
+
+ int hdlc=0;
+ misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
+
+ if (hdlc) {
+ switch (bc->capability) {
+ case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
+ case INFO_CAPABILITY_DIGITAL_RESTRICTED:
+ chan_misdn_log(1,bc->port," --> CONF HDLC\n");
+ bc->hdlc=1;
+ break;
+ }
+
+ }
+ /*Initialize new Jitterbuffer*/
+ {
+ misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
+
+ config_jitterbuffer(ch);
+ }
+
+ misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
+
+ ast_copy_string (ast->context,ch->context,sizeof(ast->context));
+
+ update_ec_config(bc);
+
+ {
+ int eb3;
+
+ misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
+ bc->early_bconnect=eb3;
+ }
+
+ port=bc->port;
+
+ {
+ char buf[256];
+ ast_group_t pg,cg;
+
+ misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
+ misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
+
+ chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
+ ast->pickupgroup=pg;
+ ast->callgroup=cg;
+ }
+
+ if ( orig == ORG_AST) {
+ misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
+
+ {
+ char callerid[BUFFERSIZE+1];
+ misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
+ if ( ! ast_strlen_zero(callerid) ) {
+ chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
+ {
+ int l = sizeof(bc->oad);
+ strncpy(bc->oad,callerid, l);
+ bc->oad[l-1] = 0;
+ }
+
+ }
+
+
+ misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
+ debug_numplan(port, bc->dnumplan,"TON");
+ debug_numplan(port, bc->onumplan,"LTON");
+ debug_numplan(port, bc->cpnnumplan,"CTON");
+ }
+
+
+
+ } else { /** ORIGINATOR MISDN **/
+
+ misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
+ debug_numplan(port, bc->cpnnumplan,"CTON");
+
+ char prefix[BUFFERSIZE+1]="";
+ switch( bc->onumplan ) {
+ case NUMPLAN_INTERNATIONAL:
+ misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
+ break;
+
+ case NUMPLAN_NATIONAL:
+ misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
+ break;
+ default:
+ break;
+ }
+
+ {
+ int l = strlen(prefix) + strlen(bc->oad);
+ char tmp[l+1];
+ strcpy(tmp,prefix);
+ strcat(tmp,bc->oad);
+ strcpy(bc->oad,tmp);
+ }
+
+ if (!ast_strlen_zero(bc->dad)) {
+ ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
+ }
+
+ if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
+ ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
+ }
+
+ prefix[0] = 0;
+
+ switch( bc->dnumplan ) {
+ case NUMPLAN_INTERNATIONAL:
+ misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
+ break;
+ case NUMPLAN_NATIONAL:
+ misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
+ break;
+ default:
+ break;
+ }
+
+ {
+ int l = strlen(prefix) + strlen(bc->dad);
+ char tmp[l+1];
+ strcpy(tmp,prefix);
+ strcat(tmp,bc->dad);
+ strcpy(bc->dad,tmp);
+ }
+
+ if ( strcmp(bc->dad,ast->exten)) {
+ ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
+ }
+
+ ast_set_callerid(ast, bc->oad, NULL, bc->oad);
+
+ if ( !ast_strlen_zero(bc->rad) )
+ ast->cid.cid_rdnis=strdup(bc->rad);
+
+ } /* ORIG MISDN END */
+
+ return 0;
+}
+
+
/*****************************/
/*** AST Indications Start ***/
/*****************************/
@@ -1041,9 +1555,8 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
int r;
struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
struct misdn_bchannel *newbc;
- char *opts=NULL, *ext=NULL;
+ char *opts=NULL, *ext,*tokb;
char dest_cp[256];
- char *tokb;
{
strncpy(dest_cp,dest,sizeof(dest_cp)-1);
@@ -1056,12 +1569,10 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
if (ext) {
opts=strtok_r(NULL,"/",&tokb);
} else {
- chan_misdn_log(-1,0,"misdn_call: No Extension given!\n");
+ chan_misdn_log(0,0,"misdn_call: No Extension given!\n");
return -1;
}
}
-
-
}
if (!ast) {
@@ -1076,7 +1587,6 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
return -1;
}
-
if (!ch) {
ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
ast->hangupcause=41;
@@ -1092,183 +1602,15 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
-
+
port=newbc->port;
-
- ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
- ast_copy_string(ast->exten, ext, sizeof(ast->exten));
+ strncpy(newbc->dad,ext,sizeof( newbc->dad));
+ strncpy(ast->exten,ext,sizeof(ast->exten));
- chan_misdn_log(1, 0, "* CALL: %s\n",dest);
+ chan_misdn_log(1, port, "* CALL: %s\n",dest);
chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
- {
- char context[BUFFERSIZE];
-
- misdn_cfg_get( port, MISDN_CFG_CONTEXT, context, sizeof(ast->context));
- {
- int l = sizeof(ast->context);
- strncpy(ast->context,context, l);
- ast->context[l-1] = 0;
- }
- chan_misdn_log(2, port, " --> * Setting Context to %s\n",context);
- misdn_cfg_get( port, MISDN_CFG_LANGUAGE, ast->language, BUFFERSIZE);
-
- misdn_cfg_get( port, MISDN_CFG_TXGAIN, &newbc->txgain, sizeof(int));
- misdn_cfg_get( port, MISDN_CFG_RXGAIN, &newbc->rxgain, sizeof(int));
-
- misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(newbc->te_choose_channel), sizeof(int));
-
-
- {
- char callerid[BUFFERSIZE];
- misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
- if ( ! ast_strlen_zero(callerid) ) {
- chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
- {
- int l = sizeof(newbc->oad);
- strncpy(newbc->oad,callerid, l);
- newbc->oad[l-1] = 0;
- }
- }
-
-
- misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &newbc->dnumplan, sizeof(int));
- switch (newbc->dnumplan) {
- case NUMPLAN_INTERNATIONAL:
- chan_misdn_log(2, port, " --> TON: International\n");
- break;
- case NUMPLAN_NATIONAL:
- chan_misdn_log(2, port, " --> TON: National\n");
- break;
- case NUMPLAN_SUBSCRIBER:
- chan_misdn_log(2, port, " --> TON: Subscriber\n");
- break;
- case NUMPLAN_UNKNOWN:
- chan_misdn_log(2, port, " --> TON: Unknown\n");
- break;
- /* Maybe we should cut off the prefix if present ? */
- default:
- chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
- break;
- }
-
-
- misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &newbc->onumplan, sizeof(int));
- switch (newbc->onumplan) {
- case NUMPLAN_INTERNATIONAL:
- chan_misdn_log(2, port, " --> TON: International\n");
- break;
- case NUMPLAN_NATIONAL:
- chan_misdn_log(2, port, " --> TON: National\n");
- break;
- case NUMPLAN_SUBSCRIBER:
- chan_misdn_log(2, port, " --> TON: Subscriber\n");
- break;
- case NUMPLAN_UNKNOWN:
- chan_misdn_log(2, port, " --> TON: Unknown\n");
- break;
- /* Maybe we should cut off the prefix if present ? */
- default:
- chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
- break;
- }
- }
-
-
-
-
- {
- int eb3;
-
- misdn_cfg_get( port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
- newbc->early_bconnect=eb3;
-
- }
-
-
-
- /* Will be overridden by asterisk in head! */
- {
- int pres;
-
- misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
- newbc->pres=pres?0:1;
-
- }
-
- int def_callingpres;
- misdn_cfg_get( port, MISDN_CFG_USE_CALLINGPRES, &def_callingpres, sizeof(int));
- if ( def_callingpres) {
-
- switch (ast->cid.cid_pres & 0x60){
-
- case AST_PRES_RESTRICTED:
- chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
- newbc->pres=1;
- break;
-
-
- case AST_PRES_UNAVAILABLE:
- chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
- newbc->pres=2;
- break;
-
- default:
- chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
- newbc->pres=0;
- }
-
- switch (ast->cid.cid_pres & 0x3){
-
- case AST_PRES_USER_NUMBER_UNSCREENED:
- chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
- newbc->screen=0;
- break;
-
- case AST_PRES_USER_NUMBER_PASSED_SCREEN:
- chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
- newbc->screen=1;
- break;
- case AST_PRES_USER_NUMBER_FAILED_SCREEN:
- chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
- newbc->screen=2;
- break;
-
- case AST_PRES_NETWORK_NUMBER:
- chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
- newbc->screen=3;
- break;
-
- default:
- chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
- newbc->screen=0;
- }
- }
-
-
- {
- int ec, ectr;
-
- misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
-
- misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
- if (ec == 1 ) {
- newbc->ec_enable=1;
- } else if ( ec > 1 ) {
- newbc->ec_enable=1;
- newbc->ec_deftaps=ec;
- }
-
-
- if (ectr>=0) {
- newbc->ec_training=ectr;
- }
-
- }
-
- }
-
chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
if (ast->exten) {
int l = sizeof(newbc->dad);
@@ -1278,6 +1620,7 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
newbc->rad[0]=0;
chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
+
if (AST_CID_P(ast)) {
int l = sizeof(newbc->oad);
strncpy(newbc->oad,AST_CID_P(ast), l);
@@ -1288,14 +1631,7 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
{
struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
if (!ch) { ast_verbose("No chan_list in misdn_call"); return -1;}
- ch->bc = newbc;
- ch->orginator=ORG_AST;
- ch->ast = ast;
- MISDN_ASTERISK_TECH_PVT(ast) = ch ;
-
-
-
newbc->capability=ast->transfercapability;
pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
@@ -1303,17 +1639,19 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
}
+ /* update screening and presentation */
+ update_config(ch,ORG_AST);
+
+ /* fill in some ies from channel vary*/
+ import_ch(ast, newbc, ch);
+
/* Finally The Options Override Everything */
if (opts)
misdn_set_opt_exec(ast,opts);
else
- chan_misdn_log(1,0,"NO OPTS GIVEN\n");
-
+ chan_misdn_log(2,port,"NO OPTS GIVEN\n");
- cl_queue_chan(&cl_te, ch) ;
ch->state=MISDN_CALLING;
-
- chan_misdn_trace_call(ast,1,"*->I: EVENT_CALL\n" );
r=misdn_lib_send_event( newbc, EVENT_SETUP );
@@ -1332,21 +1670,20 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
ast_setstate(ast, AST_STATE_DIALING);
-
ast->hangupcause=16;
+
+ if (newbc->nt) stop_bc_tones(ch);
+
return 0;
}
-int misdn_answer(struct ast_channel *ast)
+static int misdn_answer(struct ast_channel *ast)
{
struct chan_list *p;
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
-
- chan_misdn_trace_call(ast,1,"*->I: EVENT_ANSWER\n");
+ if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
@@ -1362,7 +1699,7 @@ int misdn_answer(struct ast_channel *ast)
}
{
- char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
+ const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
if (tmp_key ) {
chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
@@ -1378,27 +1715,35 @@ int misdn_answer(struct ast_channel *ast)
}
{
- char *async=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
- if (async) {
+ const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
+ if (nodsp) {
chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
- p->bc->async=1;
+ p->bc->nodsp=1;
+ p->bc->hdlc=0;
+ p->bc->nojitter=1;
}
}
p->state = MISDN_CONNECTED;
+ misdn_lib_echo(p->bc,0);
+ stop_indicate(p);
+
+ if ( ast_strlen_zero(p->bc->cad) ) {
+ chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
+ ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
+ }
+
misdn_lib_send_event( p->bc, EVENT_CONNECT);
start_bc_tones(p);
return 0;
}
-int misdn_digit(struct ast_channel *ast, char digit )
+static int misdn_digit(struct ast_channel *ast, char digit )
{
struct chan_list *p;
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
-
+ if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
struct misdn_bchannel *bc=p->bc;
chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
@@ -1452,14 +1797,13 @@ int misdn_digit(struct ast_channel *ast, char digit )
}
-int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
+static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
{
struct chan_list *p;
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
+ if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
- chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s Holded:%d L3id:%x\n", misdn_get_ch_state(p), p->holded, p->l3id);
+ chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
p->ast = ast ;
p->state=MISDN_CONNECTED;
@@ -1468,29 +1812,16 @@ int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
}
-int misdn_transfer (struct ast_channel *ast, char *dest)
-{
- struct chan_list *p;
-
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
-
- chan_misdn_log(1, p->bc?p->bc->port:0, "* IND : Got Transfer %s\n",dest);
- return 0;
-}
-
-
-int misdn_indication(struct ast_channel *ast, int cond)
+static int misdn_indication(struct ast_channel *ast, int cond)
{
struct chan_list *p;
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) {
+ if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
return -1;
}
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
if (!p->bc ) {
chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
@@ -1498,56 +1829,85 @@ int misdn_indication(struct ast_channel *ast, int cond)
return -1;
}
- chan_misdn_log(1, p->bc->port, "* IND : Indication from %s\n",ast->exten);
+ chan_misdn_log(1, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
switch (cond) {
case AST_CONTROL_BUSY:
chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
ast_setstate(ast,AST_STATE_BUSY);
-
+
p->bc->out_cause=17;
if (p->state != MISDN_CONNECTED) {
+ start_bc_tones(p);
misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
- manager_send_tone(p->bc, TONE_BUSY);
} else {
- chan_misdn_log(0, p->bc->port, " --> !! Got Busy in Connected State !?! port:%d ast:%s\n",
- p->bc->port, ast->name);
+ chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
}
+ return -1;
break;
case AST_CONTROL_RING:
chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
+ return -1;
break;
+
case AST_CONTROL_RINGING:
- if ( p->state == MISDN_ALERTING) {
- chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I ws Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
- break;
+ switch (p->state) {
+ case MISDN_ALERTING:
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
+ break;
+ case MISDN_CONNECTED:
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
+ return -1;
+ break;
+ default:
+ p->state=MISDN_ALERTING;
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
+ misdn_lib_send_event( p->bc, EVENT_ALERTING);
+
+ if (p->other_ch && p->other_ch->bc) {
+ if (misdn_inband_avail(p->other_ch->bc)) {
+ chan_misdn_log(1,p->bc->port, " --> other End is mISDN and has inband info available\n");
+ break;
+ }
+
+ if (!p->other_ch->bc->nt) {
+ chan_misdn_log(1,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
+ break;
+ }
+ }
+
+ chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
+ ast_setstate(ast,AST_STATE_RINGING);
+
+ if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio )
+ chan_misdn_log(1,p->bc->port, " --> incoming_early_audio off\n");
+ else
+ return -1;
}
- p->state=MISDN_ALERTING;
-
- chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
-
- misdn_lib_send_event( p->bc, EVENT_ALERTING);
-
- manager_send_tone(p->bc, TONE_ALERTING);
- chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
- ast_setstate(ast,AST_STATE_RINGING);
break;
-
case AST_CONTROL_ANSWER:
chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
+ start_bc_tones(p);
break;
case AST_CONTROL_TAKEOFFHOOK:
chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
+ return -1;
break;
case AST_CONTROL_OFFHOOK:
chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
+ return -1;
break;
case AST_CONTROL_FLASH:
chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
break;
case AST_CONTROL_PROGRESS:
chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
+ misdn_lib_send_event( p->bc, EVENT_PROGRESS);
+ break;
+ case AST_CONTROL_PROCEEDING:
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
+ misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
break;
case AST_CONTROL_CONGESTION:
chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
@@ -1555,18 +1915,25 @@ int misdn_indication(struct ast_channel *ast, int cond)
p->bc->out_cause=42;
if (p->state != MISDN_CONNECTED) {
start_bc_tones(p);
- //misdn_lib_send_event( p->bc, EVENT_RELEASE_COMPLETE);
misdn_lib_send_event( p->bc, EVENT_RELEASE);
} else {
misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
}
+
if (p->bc->nt) {
- manager_send_tone(p->bc, TONE_BUSY);
+ hanguptone_indicate(p);
}
break;
case -1 :
- chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! pid:%d\n",p->bc?p->bc->pid:-1);
+ chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
+
+ stop_indicate(p);
+
+ if (p->state == MISDN_CONNECTED)
+ start_bc_tones(p);
+
break;
+
case AST_CONTROL_HOLD:
chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
break;
@@ -1574,35 +1941,29 @@ int misdn_indication(struct ast_channel *ast, int cond)
chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
break;
default:
- ast_log(LOG_WARNING, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
+ ast_log(LOG_NOTICE, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
}
return 0;
}
-int misdn_hangup(struct ast_channel *ast)
+static int misdn_hangup(struct ast_channel *ast)
{
struct chan_list *p;
struct misdn_bchannel *bc=NULL;
if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
- release_lock;
-
- chan_misdn_trace_call(ast,1,"*->I: EVENT_HANGUP cause=%d\n",ast->hangupcause);
-
ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
if (!p) {
chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
- release_unlock;
return 0 ;
}
bc=p->bc;
if (!bc) {
- release_unlock;
ast_log(LOG_WARNING,"Hangup with private but no bc ?\n");
return 0;
}
@@ -1611,31 +1972,32 @@ int misdn_hangup(struct ast_channel *ast)
MISDN_ASTERISK_TECH_PVT(ast)=NULL;
p->ast=NULL;
+ bc=p->bc;
+
if (ast->_state == AST_STATE_RESERVED) {
/* between request and call */
MISDN_ASTERISK_TECH_PVT(ast)=NULL;
- release_unlock;
cl_dequeue_chan(&cl_te, p);
free(p);
-
- misdn_lib_release(bc);
+
+ if (bc)
+ misdn_lib_release(bc);
return 0;
}
- stop_bc_tones(p);
-
- release_unlock;
-
-
-
-
-
+ p->need_hangup=0;
+ p->need_queue_hangup=0;
+
+
+ if (!p->bc->nt)
+ stop_bc_tones(p);
+
{
- char *varcause=NULL;
- bc->cause=ast->hangupcause?ast->hangupcause:16;
+ const char *varcause=NULL;
+ bc->out_cause=ast->hangupcause?ast->hangupcause:16;
if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
(varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
@@ -1647,6 +2009,7 @@ int misdn_hangup(struct ast_channel *ast)
chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
+ chan_misdn_log(1, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
switch (p->state) {
case MISDN_CALLING:
@@ -1656,81 +2019,112 @@ int misdn_hangup(struct ast_channel *ast)
case MISDN_HOLDED:
case MISDN_DIALING:
start_bc_tones(p);
- manager_send_tone(bc, TONE_BUSY);
- p->state=MISDN_CLEANING;
-
- misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
-
+ hanguptone_indicate(p);
+
+ if (bc->need_disconnect)
+ misdn_lib_send_event( bc, EVENT_DISCONNECT);
+ break;
+
+ case MISDN_CALLING_ACKNOWLEDGE:
+ start_bc_tones(p);
+ hanguptone_indicate(p);
+
+ if (bc->need_disconnect)
+ misdn_lib_send_event( bc, EVENT_DISCONNECT);
break;
case MISDN_ALERTING:
- chan_misdn_log(2, bc->port, " --> * State Alerting\n");
-
+ case MISDN_PROGRESS:
+ case MISDN_PROCEEDING:
if (p->orginator != ORG_AST)
- manager_send_tone(bc, TONE_BUSY);
+ hanguptone_indicate(p);
- p->state=MISDN_CLEANING;
- misdn_lib_send_event( bc, EVENT_DISCONNECT);
+ /*p->state=MISDN_CLEANING;*/
+ if (bc->need_disconnect)
+ misdn_lib_send_event( bc, EVENT_DISCONNECT);
break;
case MISDN_CONNECTED:
+ case MISDN_PRECONNECTED:
/* Alerting or Disconect */
- chan_misdn_log(2, bc->port, " --> * State Connected\n");
- start_bc_tones(p);
- manager_send_tone(bc, TONE_BUSY);
- misdn_lib_send_event( bc, EVENT_DISCONNECT);
-
+ if (p->bc->nt) {
+ start_bc_tones(p);
+ hanguptone_indicate(p);
+ p->bc->progress_indicator=8;
+ }
+ if (bc->need_disconnect)
+ misdn_lib_send_event( bc, EVENT_DISCONNECT);
+
+ /*p->state=MISDN_CLEANING;*/
+ break;
+ case MISDN_DISCONNECTED:
+ misdn_lib_send_event( bc, EVENT_RELEASE);
p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
break;
+ case MISDN_RELEASED:
case MISDN_CLEANING:
+ p->state=MISDN_CLEANING;
+ break;
+
+ case MISDN_BUSY:
break;
case MISDN_HOLD_DISCONNECT:
/* need to send release here */
- chan_misdn_log(2, bc->port, " --> state HOLD_DISC\n");
chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
+ bc->out_cause=-1;
misdn_lib_send_event(bc,EVENT_RELEASE);
+ p->state=MISDN_CLEANING;
break;
default:
- /* Alerting or Disconect */
- if (bc->nt)
+ if (bc->nt) {
+ bc->out_cause=-1;
misdn_lib_send_event(bc, EVENT_RELEASE);
- else
- misdn_lib_send_event(bc, EVENT_DISCONNECT);
- p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
+ p->state=MISDN_CLEANING;
+ } else {
+ if (bc->need_disconnect)
+ misdn_lib_send_event(bc, EVENT_DISCONNECT);
+ }
}
+
+ p->state=MISDN_CLEANING;
}
- chan_misdn_log(1, bc->port, "Channel: %s hanguped\n",ast->name);
+
+ chan_misdn_log(1, bc->port, "Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
return 0;
}
-struct ast_frame *misdn_read(struct ast_channel *ast)
+static struct ast_frame *misdn_read(struct ast_channel *ast)
{
struct chan_list *tmp;
+ int len;
- char blah[255];
- int len =0 ;
-
- if (!ast) return NULL;
- if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) return NULL;
- if (!tmp->bc) return NULL;
-
-
- read(tmp->pipe[0],blah,sizeof(blah));
-
-
- len = misdn_ibuf_usedcount(tmp->bc->astbuf);
+ if (!ast) {
+ chan_misdn_log(1,0,"misdn_read called without ast\n");
+ return NULL;
+ }
+ if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) {
+ chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
+ return NULL;
+ }
+ if (!tmp->bc) {
+ chan_misdn_log(1,0,"misdn_read called without bc\n");
+ return NULL;
+ }
- /*shrinken len if necessary, we transmit at maximum 4k*/
- len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf);
-
- misdn_ibuf_memcpy_r(tmp->ast_rd_buf, tmp->bc->astbuf,len);
+ len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
+ if (len<=0) {
+ /* we hangup here, since our pipe is closed */
+ chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
+ return NULL;
+ }
+
tmp->frame.frametype = AST_FRAME_VOICE;
tmp->frame.subclass = AST_FORMAT_ALAW;
tmp->frame.datalen = len;
@@ -1739,41 +2133,59 @@ struct ast_frame *misdn_read(struct ast_channel *ast)
tmp->frame.offset= 0 ;
tmp->frame.src = NULL;
tmp->frame.data = tmp->ast_rd_buf ;
-
- chan_misdn_trace_call(tmp->ast,3,"*->I: EVENT_READ len=%d\n",len);
+
+ if (tmp->faxdetect || tmp->ast_dsp ) {
+ return process_ast_dsp(tmp, &tmp->frame);
+ }
+
return &tmp->frame;
}
-int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
+
+static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
{
- struct chan_list *p;
+ struct chan_list *ch;
int i = 0;
- if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
+ if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
- if (!p->bc ) {
+ if (!ch->bc ) {
ast_log(LOG_WARNING, "private but no bc\n");
return -1;
}
- if (p->bc->tone != TONE_NONE)
- manager_send_tone(p->bc,TONE_NONE);
-
-
- if (p->holded ) {
- chan_misdn_log(5, p->bc->port, "misdn_write: Returning because holded\n");
+ if (ch->state == MISDN_HOLDED) {
+ chan_misdn_log(8, ch->bc->port, "misdn_write: Returning because holded\n");
return 0;
}
- if (p->notxtone) {
- chan_misdn_log(5, p->bc->port, "misdn_write: Returning because notxone\n");
+ if (ch->notxtone) {
+ chan_misdn_log(9, ch->bc->port, "misdn_write: Returning because notxone\n");
+ return 0;
+ }
+
+
+ if ( !frame->subclass) {
+ chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
return 0;
}
if ( !(frame->subclass & prefformat)) {
- chan_misdn_log(0, p->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
+
+ chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
+ return 0;
}
+
+ if ( !frame->samples ) {
+ chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
+ return 0;
+ }
+
+ if ( ! ch->bc->addr ) {
+ chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
+ return 0;
+ }
#if MISDN_DEBUG
{
@@ -1785,13 +2197,48 @@ int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
printf ("\n");
}
#endif
- chan_misdn_trace_call(ast,3,"*->I: EVENT_WRITE len=%d\n",frame->samples);
- i= manager_tx2misdn_frm(p->bc, frame->data, frame->samples);
+
+
+ switch (ch->bc->bc_state) {
+ case BCHAN_ACTIVATED:
+ case BCHAN_BRIDGED:
+ break;
+ default:
+ if (!ch->dropped_frame_cnt)
+ chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state);
+
+ ch->dropped_frame_cnt++;
+ if (ch->dropped_frame_cnt > 100) {
+ ch->dropped_frame_cnt=0;
+ chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x dropped > 100 frames!\n",frame->samples,ch->bc->addr);
+
+ }
+
+ return 0;
+ }
+
+ chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
+
+ if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
+ /* Buffered Transmit (triggert by read from isdn side)*/
+ if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
+ if (ch->bc->active)
+ cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
+ }
+
+ } else {
+ /*transmit without jitterbuffer*/
+ i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
+ }
+
+
return 0;
}
+
+
enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
struct ast_channel *c1, int flags,
struct ast_frame **fo,
@@ -1819,47 +2266,69 @@ enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
int bridging;
misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
if (bridging) {
- int ecwb;
- misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
- if ( !ecwb ) {
- chan_misdn_log(0, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
+ int ec;
+ misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+ if ( ec ) {
+ chan_misdn_log(2, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
ch1->bc->ec_enable=0;
manager_ec_disable(ch1->bc);
}
- misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
- if ( !ecwb ) {
- chan_misdn_log(0, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
+ misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+ if ( ec ) {
+ chan_misdn_log(2, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
ch2->bc->ec_enable=0;
- manager_ec_disable(ch2->bc);
+ manager_ec_disable(ch2->bc);
}
/* trying to make a mISDN_dsp conference */
- chan_misdn_log(0, ch1->bc->port, "I SEND: Making conference with Number:%d\n", (ch1->bc->pid<<1) +1);
-
+ chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
+
misdn_lib_bridge(ch1->bc,ch2->bc);
}
- chan_misdn_log(1, ch1->bc->port, "* Makeing Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
-
+ chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
+
+
+ if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
+ ch1->ignore_dtmf=1;
+
+ if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
+ ch2->ignore_dtmf=1;
+
+
while(1) {
to=-1;
who = ast_waitfor_n(carr, 2, &to);
if (!who) {
- ast_log(LOG_DEBUG,"misdn_bridge: empty read\n");
- continue;
+ ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
+ break;
}
f = ast_read(who);
if (!f || f->frametype == AST_FRAME_CONTROL) {
/* got hangup .. */
+
+ if (!f)
+ chan_misdn_log(1,ch1->bc->port,"Read Null Frame\n");
+ else
+ chan_misdn_log(1,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
+
*fo=f;
*rc=who;
break;
}
-
-
+
+ if ( f->frametype == AST_FRAME_DTMF ) {
+ chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
+
+ *fo=f;
+ *rc=who;
+ break;
+ }
+
+
if (who == c0) {
ast_write(c1,f);
}
@@ -1868,20 +2337,67 @@ enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
}
}
-
- if (bridging) {
- misdn_lib_split_bridge(ch1->bc,ch2->bc);
+
+ chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
+
+ misdn_lib_split_bridge(ch1->bc,ch2->bc);
+
+
+ return AST_BRIDGE_COMPLETE;
+}
+
+/** AST INDICATIONS END **/
+
+static int dialtone_indicate(struct chan_list *cl)
+{
+ const struct tone_zone_sound *ts= NULL;
+ struct ast_channel *ast=cl->ast;
+
+
+ int nd=0;
+ misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
+
+ if (nd) {
+ chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
+ return 0;
}
-
+
+ chan_misdn_log(3,cl->bc->port," --> Dial\n");
+ ts=ast_get_indication_tone(ast->zone,"dial");
+ cl->ts=ts;
+
+ if (ts) {
+ cl->notxtone=0;
+ cl->norxtone=0;
+ ast_playtones_start(ast,0, ts->data, 0);
+ chan_misdn_log(4,cl->bc->port,"Starting Playtones\n");
+ misdn_lib_tone_generator_start(cl->bc);
+ }
+
+ return 0;
+}
+
+static int hanguptone_indicate(struct chan_list *cl)
+{
+ misdn_lib_send_tone(cl->bc,TONE_HANGUP);
+ return 0;
+}
+
+static int stop_indicate(struct chan_list *cl)
+{
+ struct ast_channel *ast=cl->ast;
+ chan_misdn_log(3,cl->bc->port," --> None\n");
+ misdn_lib_tone_generator_stop(cl->bc);
+ ast_playtones_stop(ast);
+ /*ast_deactivate_generator(ast);*/
+
return 0;
}
-/** AST INDICATIONS END **/
static int start_bc_tones(struct chan_list* cl)
{
- manager_bchannel_activate(cl->bc);
- manager_send_tone(cl->bc ,TONE_NONE);
+ misdn_lib_tone_generator_stop(cl->bc);
cl->notxtone=0;
cl->norxtone=0;
return 0;
@@ -1889,9 +2405,8 @@ static int start_bc_tones(struct chan_list* cl)
static int stop_bc_tones(struct chan_list *cl)
{
- if (cl->bc) {
- manager_bchannel_deactivate(cl->bc);
- }
+ if (!cl) return -1;
+
cl->notxtone=1;
cl->norxtone=1;
@@ -1899,16 +2414,21 @@ static int stop_bc_tones(struct chan_list *cl)
}
-struct chan_list *init_chan_list(void)
+static struct chan_list *init_chan_list(int orig)
{
struct chan_list *cl=malloc(sizeof(struct chan_list));
if (!cl) {
- chan_misdn_log(0, 0, "misdn_request: malloc failed!");
+ chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
return NULL;
}
memset(cl,0,sizeof(struct chan_list));
+
+ cl->orginator=orig;
+ cl->need_queue_hangup=1;
+ cl->need_hangup=1;
+ cl->need_busy=1;
return cl;
@@ -1918,30 +2438,22 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
{
struct ast_channel *tmp = NULL;
- char group[BUFFERSIZE]="";
+ char group[BUFFERSIZE+1]="";
char buf[128];
char buf2[128], *ext=NULL, *port_str;
char *tokb=NULL, *p=NULL;
int channel=0, port=0;
struct misdn_bchannel *newbc = NULL;
- struct chan_list *cl=init_chan_list();
+ struct chan_list *cl=init_chan_list(ORG_AST);
+
+ sprintf(buf,"%s/%s",misdn_type,(char*)data);
+ ast_copy_string(buf2,data, 128);
- sprintf(buf,"%s/%s",type,(char*)data);
- strncpy(buf2,data, 128);
- buf2[127] = 0;
port_str=strtok_r(buf2,"/", &tokb);
ext=strtok_r(NULL,"/", &tokb);
- /*
- if (!ext) {
- ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITH WRONG ARGS, check extension.conf\n",ext);
-
- return NULL;
- }
- */
-
if (port_str) {
if (port_str[0]=='g' && port_str[1]==':' ) {
/* We make a group call lets checkout which ports are in my group */
@@ -1951,11 +2463,11 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
}
else if ((p = strchr(port_str, ':'))) {
- // we have a preselected channel
+ /* we have a preselected channel */
*p = 0;
channel = atoi(++p);
port = atoi(port_str);
- chan_misdn_log(2, port, " --> Call on preselected Channel (%d) on Port %d\n", channel, port);
+ chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
}
else {
port = atoi(port_str);
@@ -1969,7 +2481,7 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
if (!ast_strlen_zero(group)) {
- char cfg_group[BUFFERSIZE];
+ char cfg_group[BUFFERSIZE+1];
struct robin_list *rr = NULL;
if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
@@ -1993,8 +2505,9 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
if (port >= port_start)
next_chan = 1;
- if (port < port_start && next_chan) {
- if (++robin_channel >= MAX_BCHANS) {
+ if (port <= port_start && next_chan) {
+ int maxbchans=misdn_lib_get_maxchans(port);
+ if (++robin_channel >= maxbchans) {
robin_channel = 1;
}
next_chan = 0;
@@ -2003,17 +2516,25 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
if (!strcasecmp(cfg_group, group)) {
- int l1, port_up;
-
- misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
- port_up = misdn_lib_port_up(port);
+ int port_up;
+ int check;
+ misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
+ port_up = misdn_lib_port_up(port, check);
+
+ if (check && !port_up)
+ chan_misdn_log(1,port,"L1 is not Up on this Port\n");
- if ((l1 && port_up) || !l1) {
+ if (check && port_up<0) {
+ ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
+ }
+
+
+ if ( port_up>0 ) {
newbc = misdn_lib_get_free_bc(port, robin_channel);
if (newbc) {
chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
if (port_up)
- chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
+ chan_misdn_log(4, port, "portup:%d\n", port_up);
rr->port = newbc->port;
rr->channel = newbc->channel;
break;
@@ -2024,7 +2545,7 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
} while (!newbc && robin_channel != rr->channel);
if (!newbc)
- chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
+ chan_misdn_log(-1, port, " Failed! No free channel in group %d!", group);
}
else {
@@ -2032,16 +2553,17 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
port=misdn_cfg_get_next_port(port)) {
misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
-
+
+ chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
if (!strcasecmp(cfg_group, group)) {
- int l1, port_up;
+ int port_up;
+ int check;
+ misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
+ port_up = misdn_lib_port_up(port, check);
- misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
- port_up = misdn_lib_port_up(port);
-
- chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
+ chan_misdn_log(4, port, "portup:%d\n", port_up);
- if ((l1 && port_up) || !l1) {
+ if ( port_up>0 ) {
newbc = misdn_lib_get_free_bc(port, 0);
if (newbc)
break;
@@ -2057,20 +2579,45 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
}
if (!newbc) {
- chan_misdn_log(1, 0, " --> ! No free channel chan ext:%s even after Group Call\n",ext);
- chan_misdn_log(1, 0, " --> SEND: State Down\n");
+ chan_misdn_log(-1, 0, "Could not create channel on port:%d with extensions:%s\n",port,ext);
return NULL;
}
-
+
+ /* create ast_channel and link all the objects together */
cl->bc=newbc;
- tmp = misdn_new(cl, AST_STATE_RESERVED, buf, "default", ext, ext, format, port, channel);
+ tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
+ cl->ast=tmp;
+
+ /* register chan in local list */
+ cl_queue_chan(&cl_te, cl) ;
+
+ /* fill in the config into the objects */
+ read_config(cl, ORG_AST);
+
+ /* important */
+ cl->need_hangup=0;
return tmp;
}
-struct ast_channel_tech misdn_tech = {
+int misdn_send_text (struct ast_channel *chan, const char *text)
+{
+ struct chan_list *tmp=chan->tech_pvt;
+
+ if (tmp && tmp->bc) {
+ ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
+ misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
+ } else {
+ ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static struct ast_channel_tech misdn_tech = {
.type="mISDN",
.description="Channel driver for mISDN Support (Bri/Pri)",
.capabilities= AST_FORMAT_ALAW ,
@@ -2084,11 +2631,11 @@ struct ast_channel_tech misdn_tech = {
.write=misdn_write,
.indicate=misdn_indication,
.fixup=misdn_fixup,
+ .send_text=misdn_send_text,
.properties=0
- /* .transfer=misdn_transfer */
};
-struct ast_channel_tech misdn_tech_wo_bridge = {
+static struct ast_channel_tech misdn_tech_wo_bridge = {
.type="mISDN",
.description="Channel driver for mISDN Support (Bri/Pri)",
.capabilities=AST_FORMAT_ALAW ,
@@ -2101,69 +2648,64 @@ struct ast_channel_tech misdn_tech_wo_bridge = {
.write=misdn_write,
.indicate=misdn_indication,
.fixup=misdn_fixup,
+ .send_text=misdn_send_text,
.properties=0
- /* .transfer=misdn_transfer */
};
-unsigned long glob_channel=0;
+static unsigned long glob_channel=0;
-struct ast_channel *misdn_new(struct chan_list *chlist, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c)
+static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
{
struct ast_channel *tmp;
tmp = ast_channel_alloc(1);
if (tmp) {
- chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s ctx:%s\n",exten,callerid, context);
+ chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
if (c<=0) {
c=glob_channel++;
snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
- type, port, c);
+ misdn_type, port, c);
} else {
snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
- type, port, c);
+ misdn_type, port, c);
}
- tmp->type = type;
-
+ tmp->type = misdn_type;
+
tmp->nativeformats = prefformat;
+
tmp->readformat = format;
+ tmp->rawreadformat = format;
tmp->writeformat = format;
+ tmp->rawwriteformat = format;
tmp->tech_pvt = chlist;
-
+
int bridging;
misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
if (bridging)
tmp->tech = &misdn_tech;
else
tmp->tech = &misdn_tech_wo_bridge;
-
-
+
tmp->writeformat = format;
tmp->readformat = format;
tmp->priority=1;
-
- if (context) {
- ast_copy_string(tmp->context, context, sizeof(tmp->context));
- } else {
- chan_misdn_log(1,0,"misdn_new: no context given.\n");
- }
-
- if (exten) {
+ if (exten)
ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
- } else {
+ else
chan_misdn_log(1,0,"misdn_new: no exten given.\n");
- }
if (callerid) {
char *cid_name, *cid_num;
ast_callerid_parse(callerid, &cid_name, &cid_num);
+
if (!ast_strlen_zero(cid_num)) {
tmp->cid.cid_num = strdup(cid_num);
tmp->cid.cid_ani = strdup(cid_num);
@@ -2180,193 +2722,107 @@ struct ast_channel *misdn_new(struct chan_list *chlist, int state, char * name,
}
- if (chlist->bc) {
- int port=chlist->bc->port;
- misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
-
- {
- char buf[256];
- ast_group_t pg,cg;
-
- misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
- misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
-
- chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
- tmp->pickupgroup=pg;
- tmp->callgroup=cg;
- }
- misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
- misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
- chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
-
- } else {
- chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
- }
-
ast_setstate(tmp, state);
if (state == AST_STATE_RING)
tmp->rings = 1;
else
tmp->rings = 0;
+
+
} else {
- ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
- chan_misdn_log(0,0,"Unable to allocate channel structure\n");
+ chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
}
return tmp;
}
-
-int misdn_tx2ast_frm(struct chan_list * tmp, char * buf, int len )
+struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
{
- struct ast_frame frame;
-
- /* If in hold state we drop frame .. */
- if (tmp->holded ) return 0;
-
- switch(tmp->state) {
- case MISDN_CLEANING:
- case MISDN_EXTCANTMATCH:
- case MISDN_WAITING4DIGS:
- return 0;
- default:
- break;
- }
-
- if (tmp->norxtone) {
- chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
- return 0;
+ struct ast_frame *f,*f2;
+ if (tmp->trans)
+ f2=ast_translate(tmp->trans, frame,0);
+ else {
+ chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
+ return NULL;
}
- frame.frametype = AST_FRAME_VOICE;
- frame.subclass = AST_FORMAT_ALAW;
- frame.datalen = len;
- frame.samples = len ;
- frame.mallocd =0 ;
- frame.offset= 0 ;
- frame.src = NULL;
- frame.data = buf ;
-
- if (tmp->faxdetect || tmp->ast_dsp ) {
- struct ast_frame *f,*f2;
- if (tmp->trans)
- f2=ast_translate(tmp->trans, &frame,0);
- else {
- chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
- return 0;
- }
-
- f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
- if (f && (f->frametype == AST_FRAME_DTMF)) {
- ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
- if (f->subclass == 'f' && tmp->faxdetect) {
- /* Fax tone -- Handle and return NULL */
- struct ast_channel *ast = tmp->ast;
- if (!tmp->faxhandled) {
- tmp->faxhandled++;
- if (strcmp(ast->exten, "fax")) {
- if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
- /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
- pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
- if (ast_async_goto(ast, ast->context, "fax", 1))
- ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
- } else
- ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
+ f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
+ if (f && (f->frametype == AST_FRAME_DTMF)) {
+ ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
+ if (f->subclass == 'f' && tmp->faxdetect) {
+ /* Fax tone -- Handle and return NULL */
+ struct ast_channel *ast = tmp->ast;
+ if (!tmp->faxhandled) {
+ tmp->faxhandled++;
+ if (strcmp(ast->exten, "fax")) {
+ if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
+ /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
+ pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
+ if (ast_async_goto(ast, ast->context, "fax", 1))
+ ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
} else
- ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
+ ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
} else
- ast_log(LOG_DEBUG, "Fax already handled\n");
- frame.frametype = AST_FRAME_NULL;
- frame.subclass = 0;
- f = &frame;
- } else if ( tmp->ast_dsp) {
- struct ast_frame fr;
- memset(&fr, 0 , sizeof(fr));
- fr.frametype = AST_FRAME_DTMF;
- fr.subclass = f->subclass ;
- fr.src=NULL;
- fr.data = NULL ;
- fr.datalen = 0;
- fr.samples = 0 ;
- fr.mallocd =0 ;
- fr.offset= 0 ;
-
- chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
- ast_queue_frame(tmp->ast, &fr);
-
- frame.frametype = AST_FRAME_NULL;
- frame.subclass = 0;
- f = &frame;
- }
+ ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
+ } else
+ ast_log(LOG_DEBUG, "Fax already handled\n");
+
+ } else if ( tmp->ast_dsp) {
+ chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
+ return f;
}
}
-
- if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
-#if MISDN_DEBUG
- int i, max=5>len?len:5;
-
- printf("write2* %p %d bytes: ",tmp, len);
-
- for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
- printf ("\n");
-#endif
- chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
- ast_queue_frame(tmp->ast,&frame);
-
- } else {
- ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
- }
-
- return 0;
+
+ frame->frametype = AST_FRAME_NULL;
+ frame->subclass = 0;
+ return frame;
}
-/** Channel Queue ***/
-struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
+static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
{
struct chan_list *help=list;
for (;help; help=help->next) {
- if (help->l3id == l3id ) return help;
+ if (help->bc == bc) return help;
}
- chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
+ chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
return NULL;
}
-struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
+static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
{
struct chan_list *help=list;
for (;help; help=help->next) {
- if (help->bc == bc) return help;
+ if (help->bc->pid == pid) return help;
}
- chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
+ chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
return NULL;
}
-
-struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
+static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
{
struct chan_list *help=list;
- chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
+ chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
for (;help; help=help->next) {
chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
if (help->bc->port == bc->port
&& help->bc->holded ) return help;
}
- chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
+ chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
return NULL;
}
-void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
+static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
{
chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
@@ -2382,12 +2838,13 @@ void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
ast_mutex_unlock(&cl_te_lock);
}
-void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
+static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
{
if (chan->dsp)
ast_dsp_free(chan->dsp);
if (chan->trans)
ast_translator_free_path(chan->trans);
+
ast_mutex_lock(&cl_te_lock);
@@ -2419,35 +2876,88 @@ void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
/** Channel Queue End **/
+int pbx_start_chan(struct chan_list *ch)
+{
+ int ret=ast_pbx_start(ch->ast);
+
+ if (ret>=0)
+ ch->need_hangup=0;
+ else
+ ch->need_hangup=1;
+
+ return ret;
+}
+
+static void hangup_chan(struct chan_list *ch)
+{
+ if (!ch) {
+ cb_log(1,0,"Cannot hangup chan, no ch\n");
+ return;
+ }
+
+ cb_log(1,ch->bc?ch->bc->port:0,"hangup_chan\n");
+
+ if (ch->need_hangup)
+ {
+ cb_log(1,ch->bc->port,"-> hangup\n");
+ send_cause2ast(ch->ast,ch->bc,ch);
+ ch->need_hangup=0;
+ ch->need_queue_hangup=0;
+ if (ch->ast)
+ ast_hangup(ch->ast);
+ return;
+ }
+
+ if (!ch->need_queue_hangup) {
+ cb_log(1,ch->bc->port,"No need to queue hangup\n");
+ }
+
+ ch->need_queue_hangup=0;
+ if (ch->ast) {
+ send_cause2ast(ch->ast,ch->bc,ch);
+
+ if (ch->ast)
+ ast_queue_hangup(ch->ast);
+ cb_log(1,ch->bc->port,"-> queue_hangup\n");
+ } else {
+ cb_log(1,ch->bc->port,"Cannot hangup chan, no ast\n");
+ }
+}
/** Isdn asks us to release channel, pendant to misdn_hangup **/
static void release_chan(struct misdn_bchannel *bc) {
struct ast_channel *ast=NULL;
-
{
struct chan_list *ch=find_chan_by_bc(cl_te, bc);
- if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
+ if (!ch) {
+ chan_misdn_log(0, bc->port, "release_chan: Ch not found!\n");
+ return;
+ }
- release_lock;
if (ch->ast) {
ast=ch->ast;
}
- release_unlock;
- chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
+ chan_misdn_log(1, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
+
+ /*releaseing jitterbuffer*/
+ if (ch->jb ) {
+ misdn_jb_destroy(ch->jb);
+ ch->jb=NULL;
+ } else {
+ if (!bc->nojitter)
+ chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
+ }
+
if (ch) {
- if (ast)
- chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
close(ch->pipe[0]);
close(ch->pipe[1]);
+
- if (ast && MISDN_ASTERISK_PVT(ast)) {
+ if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch));
chan_misdn_log(3, bc->port, " --> * State Down\n");
- /* copy cause */
- send_cause2ast(ast,bc);
-
MISDN_ASTERISK_TECH_PVT(ast)=NULL;
@@ -2455,58 +2965,9 @@ static void release_chan(struct misdn_bchannel *bc) {
chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
ast_setstate(ast, AST_STATE_DOWN);
}
-
- switch(ch->state) {
- case MISDN_EXTCANTMATCH:
- case MISDN_WAITING4DIGS:
- {
- chan_misdn_log(3, bc->port, " --> * State Wait4dig | ExtCantMatch\n");
- ast_hangup(ast);
- }
- break;
-
- case MISDN_DIALING:
- case MISDN_CALLING_ACKNOWLEDGE:
- case MISDN_PROGRESS:
- chan_misdn_log(2, bc->port, "* --> In State Dialin\n");
- chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
-
-
- ast_queue_hangup(ast);
- break;
- case MISDN_CALLING:
-
- chan_misdn_log(2, bc->port, "* --> In State Callin\n");
-
- if (!bc->nt) {
- chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
- ast_queue_hangup(ast);
- } else {
- chan_misdn_log(2, bc->port, "* --> Hangup\n");
- ast_queue_hangup(ast);
- //ast_hangup(ast);
- }
- break;
-
- case MISDN_CLEANING:
- /* this state comes out of ast so we mustnt call a ast function ! */
- chan_misdn_log(2, bc->port, "* --> In StateCleaning\n");
- break;
- case MISDN_HOLD_DISCONNECT:
- chan_misdn_log(2, bc->port, "* --> In HOLD_DISC\n");
- break;
- default:
- chan_misdn_log(2, bc->port, "* --> In State Default\n");
- chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
-
-
- if (ast && MISDN_ASTERISK_PVT(ast)) {
- ast_queue_hangup(ast);
- } else {
- chan_misdn_log (0, bc->port, "!! Not really queued!\n");
- }
- }
}
+
+ ch->state=MISDN_CLEANING;
cl_dequeue_chan(&cl_te, ch);
free(ch);
@@ -2517,7 +2978,7 @@ static void release_chan(struct misdn_bchannel *bc) {
}
/*** release end **/
-void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
+static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
{
chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
@@ -2526,14 +2987,12 @@ void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
holded_chan->state=MISDN_CONNECTED;
- holded_chan->holded=0;
misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
-
ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
}
-void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
+static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
{
char predial[256]="";
char *p = predial;
@@ -2543,7 +3002,7 @@ void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct
strncpy(predial, ast->exten, sizeof(predial) -1 );
ch->state=MISDN_DIALING;
-
+
if (bc->nt) {
int ret;
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
@@ -2556,15 +3015,20 @@ void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct
}
}
- manager_send_tone(bc,TONE_DIAL);
+ if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio )
+ chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
+ else
+ dialtone_indicate(ch);
chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, AST_CID_P(ast));
strncpy(ast->exten,"s", 2);
- if (ast_pbx_start(ast)<0) {
+ if (pbx_start_chan(ch)<0) {
ast=NULL;
- manager_send_tone(bc,TONE_BUSY);
+ hangup_chan(ch);
+ hanguptone_indicate(ch);
+
if (bc->nt)
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
else
@@ -2591,7 +3055,19 @@ void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct
-void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
+static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
+ if (!ast) {
+ chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
+ return;
+ }
+ if (!bc) {
+ chan_misdn_log(1,0,"send_cause2ast: No BC\n");
+ return;
+ }
+ if (!ch) {
+ chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
+ return;
+ }
ast->hangupcause=bc->cause;
@@ -2603,55 +3079,122 @@ void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
case 4:
case 22:
case 27:
+ /*
+ * Not Queueing the Congestion anymore, since we want to hear
+ * the inband message
+ *
chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
+ ch->state=MISDN_BUSY;
ast_queue_control(ast, AST_CONTROL_CONGESTION);
+ */
break;
case 21:
case 17: /* user busy */
+
+ ch->state=MISDN_BUSY;
+
+ if (!ch->need_busy) {
+ chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
+ break;
+ }
+
chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
ast_queue_control(ast, AST_CONTROL_BUSY);
+ ch->need_busy=0;
+
break;
}
}
+void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
+{
+ char *tmp;
+ tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
+ if (tmp) {
+ ch->other_pid=atoi(tmp);
+ chan_misdn_log(1,bc->port,"IMPORT_PID: importing pid:%s\n",tmp);
+
+ if (ch->other_pid >0) {
+ ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
+ if (ch->other_ch) ch->other_ch->other_ch=ch;
+ }
+ }
+}
+
+void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
+{
+ char tmp[32];
+
+ chan_misdn_log(1,bc->port,"EXPORT_PID: pid:%d\n",bc->pid);
+ sprintf(tmp,"%d",bc->pid);
+ pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
+}
+
+
+
/************************************************************/
/* Receive Events from isdn_lib here */
/************************************************************/
-enum event_response_e
+static enum event_response_e
cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
{
struct chan_list *ch=find_chan_by_bc(cl_te, bc);
- if (!ch)
- ch=find_chan_by_l3id(cl_te, bc->l3_id);
+ if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /* Debug Only Non-Bchan */
+ int debuglevel=1;
- if (event != EVENT_BCHAN_DATA) { /* Debug Only Non-Bchan */
- chan_misdn_log(1, bc->port, "I IND :%s oad:%s dad:%s port:%d\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->port);
- misdn_lib_log_ies(bc);
+ if ( event==EVENT_CLEANUP && !user_data)
+ debuglevel=5;
+
+ chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch?misdn_get_ch_state(ch):"none");
+ if (debuglevel==1) {
+ misdn_lib_log_ies(bc);
+ chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
+ }
}
- if (event != EVENT_SETUP) {
- if (!ch) {
- if (event != EVENT_CLEANUP )
- ast_log(LOG_WARNING, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc->l3_id, bc, manager_isdn_get_info( event), bc->port,bc->channel);
- return -1;
+ if (!ch) {
+ switch(event) {
+ case EVENT_SETUP:
+ case EVENT_DISCONNECT:
+ case EVENT_PORT_ALARM:
+ case EVENT_RETRIEVE:
+ case EVENT_NEW_BC:
+ break;
+ case EVENT_RELEASE_COMPLETE:
+ chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
+ break;
+ case EVENT_CLEANUP:
+ case EVENT_TONE_GENERATE:
+ case EVENT_BCHAN_DATA:
+ return -1;
+
+ default:
+ chan_misdn_log(1,bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc->l3_id, bc, manager_isdn_get_info( event), bc->port,bc->channel);
+ return -1;
}
}
if (ch ) {
switch (event) {
+ case EVENT_TONE_GENERATE:
+ break;
+ case EVENT_DISCONNECT:
case EVENT_RELEASE:
case EVENT_RELEASE_COMPLETE:
case EVENT_CLEANUP:
+ case EVENT_TIMEOUT:
+ if (!ch->ast)
+ chan_misdn_log(3,bc->port,"ast_hangup already called, so we have no ast ptr anymore in event(%s)\n",manager_isdn_get_info(event));
break;
default:
if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
if (event!=EVENT_BCHAN_DATA)
- ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
+ ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
return -1;
}
}
@@ -2659,13 +3202,38 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
switch (event) {
+ case EVENT_PORT_ALARM:
+ {
+ int boa=0;
+
+ misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
+ if (boa) {
+ cb_log(1,bc->port," --> blocking\n");
+ misdn_lib_port_block(bc->port);
+ }
+ }
+ break;
+
+ case EVENT_BCHAN_ACTIVATED:
+ break;
+
case EVENT_NEW_L3ID:
ch->l3id=bc->l3_id;
+ ch->addr=bc->addr;
break;
case EVENT_NEW_BC:
+ if (!ch) {
+ ch=find_holded(cl_te,bc);
+ }
+
+ if (!ch) {
+ ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
+ break;
+ }
+
if (bc)
- ch->bc=bc;
+ ch->bc=(struct misdn_bchannel*)user_data;
break;
case EVENT_DTMF_TONE:
@@ -2682,9 +3250,12 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
fr.mallocd =0 ;
fr.offset= 0 ;
- chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
-
- ast_queue_frame(ch->ast, &fr);
+ if (!ch->ignore_dtmf) {
+ chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
+ ast_queue_frame(ch->ast, &fr);
+ } else {
+ chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf);
+ }
}
break;
case EVENT_STATUS:
@@ -2694,8 +3265,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
{
int stop_tone;
misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
- if ( stop_tone && bc->tone != TONE_NONE) {
- manager_send_tone(bc,TONE_NONE);
+ if ( stop_tone ) {
+ stop_indicate(ch);
}
if (ch->state == MISDN_WAITING4DIGS ) {
@@ -2714,31 +3285,46 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
}
/* chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
- char bc_context[BUFFERSIZE];
- misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
- if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
- chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
- manager_send_tone(bc,TONE_BUSY);
+ /* Check for Pickup Request first */
+ if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
+ int ret;/** Sending SETUP_ACK**/
+ ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
+ if (ast_pickup_call(ch->ast)) {
+ hangup_chan(ch);
+ } else {
+ struct ast_channel *chan=ch->ast;
+ ch->state = MISDN_CALLING_ACKNOWLEDGE;
+ ast_setstate(chan, AST_STATE_DOWN);
+ hangup_chan(ch);
+ ch->ast=NULL;
+ break;
+ }
+ }
+
+ if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+
+ chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
+ if (bc->nt)
+ hanguptone_indicate(ch);
ch->state=MISDN_EXTCANTMATCH;
bc->out_cause=1;
- if (bc->nt)
- misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
- else
- misdn_lib_send_event(bc, EVENT_DISCONNECT );
+
+ misdn_lib_send_event(bc, EVENT_DISCONNECT );
+
break;
}
- if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
+ if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
ch->state=MISDN_DIALING;
- manager_send_tone(bc,TONE_NONE);
-/* chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->ast->context);*/
- if (ast_pbx_start(ch->ast)<0) {
- chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
- manager_send_tone(bc,TONE_BUSY);
- if (bc->nt)
- misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
- else
- misdn_lib_send_event(bc, EVENT_DISCONNECT );
+ stop_indicate(ch);
+/* chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/
+ if (pbx_start_chan(ch)<0) {
+ hangup_chan(ch);
+
+ chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n");
+ if (bc->nt) hanguptone_indicate(ch);
+
+ misdn_lib_send_event(bc, EVENT_DISCONNECT );
}
}
@@ -2771,7 +3357,6 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ast_queue_frame(ch->ast, &fr);
}
-
}
}
break;
@@ -2784,6 +3369,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
}
}
+
int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
if (!bc->nt && ! msn_valid) {
chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
@@ -2793,119 +3379,61 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
print_bearer(bc);
{
- struct chan_list *ch=init_chan_list();
+ struct chan_list *ch=init_chan_list(ORG_MISDN);
struct ast_channel *chan;
- char name[128];
- if (!ch) { chan_misdn_log(0, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
+
+ if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
ch->bc = bc;
ch->l3id=bc->l3_id;
ch->addr=bc->addr;
ch->orginator = ORG_MISDN;
+ chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
+ ch->ast = chan;
+
+ read_config(ch, ORG_MISDN);
- {
- char prefix[BUFFERSIZE]="";
- switch( bc->onumplan ) {
- case NUMPLAN_INTERNATIONAL:
- misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
- break;
-
- case NUMPLAN_NATIONAL:
- misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
- break;
-
-
- case NUMPLAN_SUBSCRIBER:
- /* dunno what to do here ? */
- break;
+ export_ch(chan, bc, ch);
- case NUMPLAN_UNKNOWN:
- break;
- default:
- break;
- }
+ ch->ast->rings=1;
+ ast_setstate(ch->ast, AST_STATE_RINGING);
- {
- int l = strlen(prefix) + strlen(bc->oad);
- char tmp[l+1];
- strcpy(tmp,prefix);
- strcat(tmp,bc->oad);
- strcpy(bc->oad,tmp);
- }
-
- if (!ast_strlen_zero(bc->oad))
- sprintf(name,"mISDN/%d/%s",bc->port,bc->oad);
- else
- sprintf(name,"mISDN/%d",bc->port);
+ int pres,screen;
+ switch (bc->pres) {
+ case 1:
+ pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
+ break;
+ case 2:
+ pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
+ break;
+ default:
+ pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
+ }
- if (!ast_strlen_zero(bc->dad)) {
- strncpy(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
- bc->orig_dad[sizeof(bc->orig_dad)-1] = 0;
- }
-
- if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
- strncpy(bc->dad,bc->keypad, sizeof(bc->dad));
- bc->dad[sizeof(bc->dad)-1] = 0;
- }
- prefix[0] = 0;
-
- switch( bc->dnumplan ) {
- case NUMPLAN_INTERNATIONAL:
- misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
- break;
-
- case NUMPLAN_NATIONAL:
- misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
- break;
-
-
- case NUMPLAN_SUBSCRIBER:
- /* dunno what to do here ? */
- break;
-
- case NUMPLAN_UNKNOWN:
- break;
+ switch (bc->screen) {
+ case 0:
+ screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
+ break;
+ case 1:
+ screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
+ break;
+ case 2:
+ screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
+ break;
+ case 3:
+ screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
+ break;
default:
- break;
- }
-
- {
- int l = strlen(prefix) + strlen(bc->dad);
- char tmp[l+1];
- strcpy(tmp,prefix);
- strcat(tmp,bc->dad);
- strcpy(bc->dad,tmp);
- }
-
- char bc_context[BUFFERSIZE];
- misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
- chan=misdn_new(ch, AST_STATE_RING,name ,bc_context, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
-
- if (!chan) {
- misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
- return 0;
- }
-
- ch->ast = chan;
- pbx_builtin_setvar_helper(ch->ast,"REDIRECTING_NUMBER",bc->rad);
-
+ screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
}
-
+ chan->cid.cid_pres=pres+screen;
- chan_misdn_trace_call(chan,1,"I->*: EVENT_SETUP\n");
-
- if ( bc->pres ) {
- chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
- } else {
- chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
- }
-
pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
chan->transfercapability=bc->capability;
-
+
switch (bc->capability) {
case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
@@ -2917,113 +3445,88 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
/** queue new chan **/
cl_queue_chan(&cl_te, ch) ;
-
- /*
- added support for s extension hope it will help those poor cretains
- which haven't overlap dial.
- */
- {
-
- misdn_cfg_get( bc->port, MISDN_CFG_LANGUAGE, chan->language, sizeof(chan->language));
-
- }
-
- {
- int eb3;
-
- misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
- bc->early_bconnect=eb3;
-
- }
- {
- int ec, ectr;
-
- misdn_cfg_get( bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
-
- misdn_cfg_get( bc->port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
- if (ec == 1 ) {
- bc->ec_enable=1;
- } else if ( ec > 1 ) {
- bc->ec_enable=1;
- bc->ec_deftaps=ec;
- }
-
- if ( ectr>=0 ) {
- bc->ec_training=ectr;
+ if (!strstr(ch->allowed_bearers,"all")) {
+ int i;
+ for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
+ if (allowed_bearers_array[i].cap == bc->capability) {
+ if ( !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) {
+ chan_misdn_log(0,bc->port,"Bearer Not allowed\b");
+ bc->out_cause=88;
+
+ ch->state=MISDN_EXTCANTMATCH;
+ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
+ return RESPONSE_OK;
+ }
+ }
+
}
}
-
- if (bc->urate>0) {
- char buf[16];
- snprintf(buf,16,"%d",bc->urate);
- pbx_builtin_setvar_helper(chan,"MISDN_URATE",buf);
- }
-
-
-
- /**
- from here on we start the PBX, so no configuration should
- be considered anymore
- **/
-
- int ai;
- misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
- if ( ai ) {
- do_immediate_setup(bc, ch , chan);
- break;
- }
-
-
- int immediate;
- misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &immediate, sizeof(int));
-
- if (ast_strlen_zero(bc->orig_dad) && immediate ) {
- do_immediate_setup(bc, ch , chan);
- break;
- }
-
/* Check for Pickup Request first */
if (!strcmp(chan->exten, ast_pickup_ext())) {
int ret;/** Sending SETUP_ACK**/
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
-
if (ast_pickup_call(chan)) {
- ast_hangup(chan);
+ hangup_chan(ch);
} else {
ch->state = MISDN_CALLING_ACKNOWLEDGE;
-
- ch->ast=NULL;
-
ast_setstate(chan, AST_STATE_DOWN);
- ast_hangup(chan);
-
+ hangup_chan(ch);
+ ch->ast=NULL;
break;
}
}
- /** Now after we've finished configuring our channel object
- we'll jump into the dialplan **/
+ /*
+ added support for s extension hope it will help those poor cretains
+ which haven't overlap dial.
+ */
+ {
+ int ai;
+ misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
+ if ( ai ) {
+ do_immediate_setup(bc, ch , chan);
+ break;
+ }
+
+
+
+ }
+
+ /* check if we should jump into s when we have no dad */
+ {
+ int im;
+ misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
+ if ( im && ast_strlen_zero(bc->dad) ) {
+ do_immediate_setup(bc, ch , chan);
+ break;
+ }
+ }
+
- char bc_context[BUFFERSIZE];
- misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
- if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
- chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
- manager_send_tone(bc,TONE_BUSY);
+ chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
+ if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+
+ chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
+
+ if (bc->nt)
+ hanguptone_indicate(ch);
ch->state=MISDN_EXTCANTMATCH;
bc->out_cause=1;
+
if (bc->nt)
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
else
- misdn_lib_send_event(bc, EVENT_DISCONNECT );
+ misdn_lib_send_event(bc, EVENT_RELEASE );
+
break;
}
- if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
+ if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
ch->state=MISDN_DIALING;
-
- if (bc->nt) {
+
+ if (bc->nt || (bc->need_more_infos && misdn_lib_is_ptp(bc->port)) ) {
int ret;
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
} else {
@@ -3031,31 +3534,53 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
}
- if (ast_pbx_start(chan)<0) {
- chan_misdn_log(0, bc->port, "ast_pbx_start returned <0 in SETUP\n");
+ if (pbx_start_chan(ch)<0) {
+ hangup_chan(ch);
+
+ chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
chan=NULL;
- manager_send_tone(bc,TONE_BUSY);
- if (bc->nt)
+
+ if (bc->nt) {
+ hanguptone_indicate(ch);
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
- else
- misdn_lib_send_event(bc, EVENT_DISCONNECT );
+ } else
+ misdn_lib_send_event(bc, EVENT_RELEASE);
}
} else {
- int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
- if (ret == -ENOCHAN) {
- ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
- misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+
+ if (bc->sending_complete) {
+ ch->state=MISDN_EXTCANTMATCH;
+ bc->out_cause=1;
+
+ if (bc->nt) {
+ chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
+ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+ } else {
+ chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
+ misdn_lib_send_event(bc, EVENT_RELEASE);
+ }
+
+ } else {
+
+ int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
+ if (ret == -ENOCHAN) {
+ ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
+ misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+ }
+ /* send tone to phone :) */
+
+ /** ADD IGNOREPAT **/
+
+ int stop_tone;
+ misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
+ if ( (!ast_strlen_zero(bc->dad)) && stop_tone )
+ stop_indicate(ch);
+ else {
+ dialtone_indicate(ch);
+ }
+
+ ch->state=MISDN_WAITING4DIGS;
}
- /* send tone to phone :) */
-
- int stop_tone;
- misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
- if ( (!ast_strlen_zero(bc->dad)) && stop_tone )
- manager_send_tone(bc,TONE_NONE);
- else
- manager_send_tone(bc,TONE_DIAL);
-
- ch->state=MISDN_WAITING4DIGS;
}
}
@@ -3094,6 +3619,10 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
misdn_inband_avail(bc) ) {
start_bc_tones(ch);
}
+
+ ch->state = MISDN_PROCEEDING;
+
+ ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
}
break;
case EVENT_PROGRESS:
@@ -3121,162 +3650,272 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
cb_log(1,bc->port,"Set State Ringing\n");
if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
- start_bc_tones(ch);
- }
+ cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
+ start_bc_tones(ch);
+ } else {
+ cb_log(1,bc->port,"We have no inband Data, the other end must create ringing\n");
+ if (ch->far_alerting) {
+ cb_log(1,bc->port,"The other end can not do ringing eh ?.. we must do all ourself..");
+ start_bc_tones(ch);
+ /*tone_indicate(ch, TONE_FAR_ALERTING);*/
+ }
+ }
}
break;
case EVENT_CONNECT:
+ {
+ /*we answer when we've got our very new L3 ID from the NT stack */
misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
+
+ struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
+
+ misdn_lib_echo(bc,0);
+ stop_indicate(ch);
+
+ if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
+ struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
+
+ chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
+ if (bridged_ch) {
+ bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
+ ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
+ }
+ }
+ }
+
+
+ /* notice that we don't break here!*/
+
case EVENT_CONNECT_ACKNOWLEDGE:
{
- bc->state=STATE_CONNECTED;
-
ch->l3id=bc->l3_id;
ch->addr=bc->addr;
start_bc_tones(ch);
- chan_misdn_trace_call(ch->ast,1,"I->*: EVENT_CONNECT\n");
ch->state = MISDN_CONNECTED;
ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
}
break;
case EVENT_DISCONNECT:
- {
-
+ /*we might not have an ch->ast ptr here anymore*/
+ if (ch) {
struct chan_list *holded_ch=find_holded(cl_te, bc);
-
-
- send_cause2ast(ch->ast,bc);
-
- if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
+
+ chan_misdn_log(3,bc->port," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->orginator, bc->nt, misdn_inband_avail(bc), ch->state);
+ if ( ch->orginator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
/* If there's inband information available (e.g. a
recorded message saying what was wrong with the
dialled number, or perhaps even giving an
alternative number, then play it instead of
immediately releasing the call */
+ chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
+
+ ch->state=MISDN_DISCONNECTED;
start_bc_tones(ch);
break;
}
/*Check for holded channel, to implement transfer*/
- if (holded_ch ) {
+ if (holded_ch && ch->ast ) {
+ cb_log(1,bc->port," --> found holded ch\n");
if (ch->state == MISDN_CONNECTED ) {
misdn_transfer_bc(ch, holded_ch) ;
- misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
- break;
}
+ hangup_chan(ch);
+ release_chan(bc);
+ break;
}
stop_bc_tones(ch);
- bc->out_cause=16;
- misdn_lib_send_event(bc,EVENT_RELEASE);
-
+ hangup_chan(ch);
}
+ bc->out_cause=-1;
+ if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
break;
case EVENT_RELEASE:
{
-
- switch ( bc->cause) {
-
- case -1:
- /*
- OK, it really sucks, this is a RELEASE from NT-Stack So we take
- it and return easylie, It seems that we've send a DISCONNECT
- before, so we should RELEASE_COMPLETE after that Disconnect
- (looks like ALERTING State at misdn_hangup !!
- */
- return RESPONSE_OK;
- break;
- }
-
-
bc->out_cause=16;
- stop_bc_tones(ch);
+ hangup_chan(ch);
release_chan(bc);
+
+ if (bc->need_release_complete)
+ misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
}
break;
case EVENT_RELEASE_COMPLETE:
{
stop_bc_tones(ch);
+ hangup_chan(ch);
+ release_chan(bc);
+ if(ch)
+ ch->state=MISDN_CLEANING;
+ }
+ break;
+ case EVENT_CLEANUP:
+ {
+ stop_bc_tones(ch);
+
+ switch(ch->state) {
+ case MISDN_CALLING:
+ bc->cause=27; /* Destination out of order */
+ break;
+ default:
+ break;
+ }
+
+ hangup_chan(ch);
release_chan(bc);
}
break;
+
+ case EVENT_TONE_GENERATE:
+ {
+ int tone_len=bc->tone_cnt;
+ struct ast_channel *ast=ch->ast;
+ void *tmp;
+ int res;
+ int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
+
+ chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
+
+ if (!ast) break;
+
+ if (!ast->generator) break;
+
+
+ tmp = ast->generatordata;
+ ast->generatordata = NULL;
+ generate = ast->generator->generate;
+
+ if (tone_len <0 || tone_len > 512 ) {
+ ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
+ tone_len=128;
+ }
+
+ res = generate(ast, tmp, tone_len, tone_len);
+ ast->generatordata = tmp;
+
+ if (res) {
+ ast_log(LOG_WARNING, "Auto-deactivating generator\n");
+ ast_deactivate_generator(ast);
+ } else {
+ bc->tone_cnt=0;
+ }
+ }
+ break;
+
case EVENT_BCHAN_DATA:
{
- chan_misdn_trace_call(ch->ast,3,"I->*: EVENT_B_DATA len=%d\n",bc->bframe_len);
-
- if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
- misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
+ if ( !misdn_cap_is_speech(ch->bc->capability) ) {
+ struct ast_frame frame;
+ /*In Data Modes we queue frames*/
+ frame.frametype = AST_FRAME_VOICE; /*we have no data frames yet*/
+ frame.subclass = AST_FORMAT_ALAW;
+ frame.datalen = bc->bframe_len;
+ frame.samples = bc->bframe_len ;
+ frame.mallocd =0 ;
+ frame.offset= 0 ;
+ frame.src = NULL;
+ frame.data = bc->bframe ;
+
+ ast_queue_frame(ch->ast,&frame);
} else {
- int len=bc->bframe_len;
- int free=misdn_ibuf_freecount(bc->astbuf);
+ fd_set wrfs;
+ struct timeval tv;
+ tv.tv_sec=0;
+ tv.tv_usec=0;
+
+ FD_ZERO(&wrfs);
+ FD_SET(ch->pipe[1],&wrfs);
- if (bc->bframe_len > free) {
- ast_log(LOG_DEBUG, "sbuf overflow!\n");
- len=misdn_ibuf_freecount(bc->astbuf);
+ int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
- if (len == 0) {
- ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
- }
+ if (!t) {
+ chan_misdn_log(9, bc->port, "Select Timed out\n");
+ break;
}
- misdn_ibuf_memcpy_w(bc->astbuf, bc->bframe, len);
+ if (t<0) {
+ chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
+ break;
+ }
- {
- char blah[1]="\0";
-#ifdef FLATTEN_JITTER
- {
- struct timeval tv;
- gettimeofday(&tv,NULL);
-
- if (tv.tv_usec % 10000 > 0 ) {
- write(ch->pipe[1], blah,sizeof(blah));
- bc->time_usec=tv.tv_usec;
- }
- }
-#else
- write(ch->pipe[1], blah,sizeof(blah));
-#endif
-
+ if (FD_ISSET(ch->pipe[1],&wrfs)) {
+ chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
+ int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
+ if (ret<=0) {
+ chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s)\n",strerror(errno));
+ }
+ } else {
+ chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
}
}
-
}
break;
case EVENT_TIMEOUT:
- break; /* Ignore now .. */
{
- switch (ch->state) {
+ if (ch && bc)
+ chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
+
+ switch (ch->state) {
case MISDN_CALLING:
- chan_misdn_log(0, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
- break;
case MISDN_DIALING:
case MISDN_PROGRESS:
- break;
+ case MISDN_ALERTING:
+ case MISDN_PROCEEDING:
+ case MISDN_CALLING_ACKNOWLEDGE:
+ if (bc->nt) {
+ bc->progress_indicator=8;
+ hanguptone_indicate(ch);
+ }
+
+ bc->out_cause=1;
+ misdn_lib_send_event(bc,EVENT_DISCONNECT);
+ break;
+
+ case MISDN_WAITING4DIGS:
+ if (bc->nt) {
+ bc->progress_indicator=8;
+ bc->out_cause=1;
+ hanguptone_indicate(ch);
+ misdn_lib_send_event(bc,EVENT_DISCONNECT);
+ } else {
+ bc->out_cause=16;
+ misdn_lib_send_event(bc,EVENT_RELEASE);
+ }
+
+ break;
+
+
+ case MISDN_CLEANING:
+ chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
+ break;
+
default:
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
}
}
break;
- case EVENT_CLEANUP:
- {
- stop_bc_tones(ch);
- release_chan(bc);
- }
- break;
+
/***************************/
/** Suplementary Services **/
/***************************/
case EVENT_RETRIEVE:
{
+ ch=find_holded(cl_te, bc);
+ if (!ch) {
+ ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
+ misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
+ break;
+ }
struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
ch->state = MISDN_CONNECTED;
@@ -3297,34 +3936,77 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
if (!hold_allowed) {
- chan_misdn_log(0, bc->port, "Hold not allowed on port:%d\n", bc->port);
+
+ chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
break;
}
+#if 0
{
struct chan_list *holded_ch=find_holded(cl_te, bc);
if (holded_ch) {
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
- chan_misdn_log(0, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
+
+ chan_misdn_log(-1, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
break;
}
}
+#endif
+ struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
- if (AST_BRIDGED_P(ch->ast)){
+ if (bridged){
+ struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
ch->state = MISDN_HOLDED;
ch->l3id = bc->l3_id;
- ast_moh_start(AST_BRIDGED_P(ch->ast), NULL);
+ bc->holded_bc=bridged_ch->bc;
misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
+
+ ast_moh_start(bridged, NULL);
} else {
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
}
}
break;
+
+ case EVENT_FACILITY:
+ print_facility(bc);
+
+ switch (bc->fac_type) {
+ case FACILITY_CALLDEFLECT:
+ {
+ struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
+ struct chan_list *ch;
+
+ if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
+ ch=MISDN_ASTERISK_TECH_PVT(bridged);
+ /*ch->state=MISDN_FACILITY_DEFLECTED;*/
+ if (ch->bc) {
+ /* todo */
+ }
+
+ }
+
+ }
+
+ break;
+ default:
+ chan_misdn_log(1, bc->port," --> not yet handled\n");
+ }
+
+ break;
+
+ case EVENT_RESTART:
+
+ stop_bc_tones(ch);
+ release_chan(bc);
+
+ break;
+
default:
- ast_log(LOG_WARNING, "Got Unknown Event\n");
+ ast_log(LOG_NOTICE, "Got Unknown Event\n");
break;
}
@@ -3341,13 +4023,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
*******************************************/
-int clearl3_true ( void ) {
- int default_clearl3;
- misdn_cfg_get( 0, MISDN_GEN_CLEAR_L3, &default_clearl3, sizeof(int));
- return default_clearl3;
-}
-
-int g_config_initialized=0;
+static int g_config_initialized=0;
int load_module(void)
{
@@ -3359,7 +4035,7 @@ int load_module(void)
if (max_ports<=0) {
ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
- return -1;
+ return 0;
}
@@ -3374,16 +4050,17 @@ int load_module(void)
{
- char tempbuf[BUFFERSIZE];
+ char tempbuf[BUFFERSIZE+1];
misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
if (strlen(tempbuf))
tracing = 1;
}
ast_mutex_init(&cl_te_lock);
- ast_mutex_init(&release_lock_mutex);
+ misdn_cfg_update_ptp();
misdn_cfg_get_ports_string(ports);
+
if (strlen(ports))
chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
@@ -3391,16 +4068,25 @@ int load_module(void)
struct misdn_lib_iface iface = {
.cb_event = cb_events,
.cb_log = chan_misdn_log,
- .cb_clearl3_true = clearl3_true
+ .cb_jb_empty = chan_misdn_jb_empty,
};
if (misdn_lib_init(ports, &iface, NULL))
chan_misdn_log(0, 0, "No te ports initialized\n");
+
+ int ntflags=0;
+ char ntfile[BUFFERSIZE+1];
+
+ misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
+ misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
+
+ misdn_lib_nt_debug_init(ntflags,ntfile);
+
}
{
if (ast_channel_register(&misdn_tech)) {
- ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
+ ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
unload_module();
return -1;
}
@@ -3418,17 +4104,30 @@ int load_module(void)
ast_cli_register(&cli_show_port);
ast_cli_register(&cli_show_stacks);
+ ast_cli_register(&cli_port_block);
+ ast_cli_register(&cli_port_unblock);
ast_cli_register(&cli_restart_port);
ast_cli_register(&cli_port_up);
+ ast_cli_register(&cli_port_down);
ast_cli_register(&cli_set_debug);
ast_cli_register(&cli_set_crypt_debug);
ast_cli_register(&cli_reload);
- ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
+ ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
"misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
"Sets mISDN opts. and optargs\n"
"\n"
+ "The available options are:\n"
+ " d - Send display text on called phone, text is the optparam\n"
+ " n - don't detect dtmf tones on called channel\n"
+ " h - make digital outgoing call\n"
+ " c - make crypted outgoing call, param is keyindex\n"
+ " e - perform echo cancelation on this channel,\n"
+ " takes taps as arguments (32,64,128,256)\n"
+ " s - send Non Inband DTMF as inband\n"
+ " vr - rxgain control\n"
+ " vt - txgain control\n"
);
@@ -3439,9 +4138,11 @@ int load_module(void)
"Supported Facilities are:\n"
"\n"
"type=calldeflect args=Nr where to deflect\n"
- "\n"
);
-
+
+
+ misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
+
chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
return 0;
@@ -3469,8 +4170,11 @@ int unload_module(void)
ast_cli_unregister(&cli_show_config);
ast_cli_unregister(&cli_show_port);
ast_cli_unregister(&cli_show_stacks);
+ ast_cli_unregister(&cli_port_block);
+ ast_cli_unregister(&cli_port_unblock);
ast_cli_unregister(&cli_restart_port);
ast_cli_unregister(&cli_port_up);
+ ast_cli_unregister(&cli_port_down);
ast_cli_unregister(&cli_set_debug);
ast_cli_unregister(&cli_set_crypt_debug);
ast_cli_unregister(&cli_reload);
@@ -3480,6 +4184,7 @@ int unload_module(void)
ast_channel_unregister(&misdn_tech);
+
free_robin_list();
misdn_cfg_destroy();
misdn_lib_destroy();
@@ -3492,6 +4197,13 @@ int unload_module(void)
return 0;
}
+int reload(void)
+{
+ reload_config();
+
+ return 0;
+}
+
int usecount(void)
{
int res;
@@ -3511,102 +4223,7 @@ char *key(void)
return ASTERISK_GPL_KEY;
}
-void chan_misdn_log(int level, int port, char *tmpl, ...)
-{
- if (! ((0 <= port) && (port <= max_ports))) {
- ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
- return;
- }
-
- va_list ap;
- char buf[1024];
-
- va_start(ap, tmpl);
- vsnprintf( buf, 1023, tmpl, ap );
- va_end(ap);
-
- if (misdn_debug_only[port] ? (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) : level <= misdn_debug[port]) {
- ast_console_puts(buf);
- }
-
- if (level <= misdn_debug[0] && tracing) {
- time_t tm = time(NULL);
- char *tmp=ctime(&tm),*p;
- char file[BUFFERSIZE];
- misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, file, BUFFERSIZE);
- FILE *fp= fopen(file, "a+");
-
- p=strchr(tmp,'\n');
- if (p) *p=':';
-
- if (!fp) {
- ast_console_puts("Error opening Tracefile: ");
- ast_console_puts(strerror(errno));
- ast_console_puts("\n");
- return ;
- }
-
- fputs(tmp,fp);
- fputs(" ", fp);
- fputs(buf, fp);
-
- fclose(fp);
- }
-}
-
-
-void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...)
-{
- va_list ap;
- char buf[1024];
- char name[1024];
-
- int trace;
- misdn_cfg_get( 0, MISDN_GEN_TRACE_CALLS, &trace, sizeof(int));
- if (!trace) return ;
-
- if (misdn_debug[0] < debug) return ;
-
- char tracedir[BUFFERSIZE];
- misdn_cfg_get( 0, MISDN_GEN_TRACE_DIR, tracedir, BUFFERSIZE);
- sprintf(name,"%s/%s.%s",tracedir, chan->uniqueid, chan->cid.cid_num );
-
- va_start(ap, tmpl);
-
- vsprintf( buf, tmpl, ap );
-
- va_end(ap);
-
- time_t tm = time(NULL);
- char *tmp=ctime(&tm),*p;
- FILE *fp= fopen(name, "a");
- int fd;
-
- if (!fp) {
- ast_console_puts("Error opening Tracefile");
- ast_console_puts(strerror(errno));
- ast_console_puts("\n");
- return ;
- }
-
- fd=fileno(fp) ;
-
- flock(fd, LOCK_EX);
-
- p=strchr(tmp,'\n');
- if (p) *p=':';
-
-
-
- fputs(tmp,fp);
- fputs(" ", fp);
- fputs(buf, fp);
- flock(fd, LOCK_UN);
-
- fclose(fp);
-
-}
/*** SOME APPS ;)***/
@@ -3615,9 +4232,10 @@ static int misdn_facility_exec(struct ast_channel *chan, void *data)
{
struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
char *tok, *tokb;
-
- if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
+ chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
+
+ if (strcasecmp(chan->tech->type,"mISDN")) {
ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
return -1;
}
@@ -3659,8 +4277,9 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
int keyidx=0;
int rxgain=0;
int txgain=0;
-
- if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
+ int change_jitter=0;
+
+ if (strcasecmp(chan->tech->type,"mISDN")) {
ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
return -1;
}
@@ -3683,7 +4302,7 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
switch(tok[0]) {
case 'd' :
- strncpy(ch->bc->display,++tok,84);
+ ast_copy_string(ch->bc->display,++tok,84);
chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
break;
@@ -3693,8 +4312,32 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
break;
case 'j':
- chan_misdn_log(1, ch->bc->port, "SETOPT: No jitter\n");
- ch->bc->nojitter=1;
+ chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
+ tok++;
+ change_jitter=1;
+
+ switch ( tok[0] ) {
+ case 'b' :
+ ch->jb_len=atoi(++tok);
+ chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n",ch->jb_len);
+ break;
+ case 't' :
+ ch->jb_upper_threshold=atoi(++tok);
+ chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n",ch->jb_upper_threshold);
+ break;
+
+ case 'n':
+ ch->bc->nojitter=1;
+ chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
+ break;
+
+ default:
+ ch->jb_len=4000;
+ ch->jb_upper_threshold=0;
+ chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n",ch->jb_len);
+ chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n",ch->jb_upper_threshold);
+ }
+
break;
case 'v':
@@ -3727,10 +4370,9 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
}
{
- int l = sizeof(ch->bc->crypt_key);
- strncpy(ch->bc->crypt_key, misdn_key_vector[keyidx], l);
- ch->bc->crypt_key[l-1] = 0;
+ ast_copy_string(ch->bc->crypt_key, misdn_key_vector[keyidx], sizeof(ch->bc->crypt_key));
}
+
chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",misdn_key_vector[keyidx]);
break;
@@ -3738,7 +4380,9 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
if (neglect) {
+ chan_misdn_log(1, ch->bc->port, " --> disabled\n");
ch->bc->ec_enable=0;
+
} else {
ch->bc->ec_enable=1;
ch->bc->orig=ch->orginator;
@@ -3752,18 +4396,12 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
case 'h':
chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
+
if (strlen(tok) > 1 && tok[1]=='1') {
- chan_misdn_log(1, ch->bc->port, "SETOPT: Digital TRANS_DIGITAL\n");
- ch->bc->async=1;
- ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
- /*ch->bc->state=STATE_CONNECTED;
- misdn_lib_setup_bc(ch->bc);*/
- } else {
- ch->bc->async=0;
- ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
- /*ch->bc->state=STATE_CONNECTED;
- misdn_lib_setup_bc(ch->bc);*/
- }
+ chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
+ ch->bc->hdlc=1;
+ }
+ ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
break;
case 's':
@@ -3798,6 +4436,10 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
break;
}
}
+
+ if (change_jitter)
+ config_jitterbuffer(ch);
+
if (ch->faxdetect || ch->ast_dsp) {
@@ -3816,3 +4458,246 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
}
+int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
+{
+ struct chan_list *ch=find_chan_by_bc(cl_te, bc);
+
+ if (ch && ch->jb) {
+ return misdn_jb_empty(ch->jb, buf, len);
+ }
+
+ return -1;
+}
+
+
+
+/*******************************************************/
+/***************** JITTERBUFFER ************************/
+/*******************************************************/
+
+
+/* allocates the jb-structure and initialise the elements*/
+struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
+{
+ int i;
+ struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
+ jb->size = size;
+ jb->upper_threshold = upper_threshold;
+ jb->wp = 0;
+ jb->rp = 0;
+ jb->state_full = 0;
+ jb->state_empty = 0;
+ jb->bytes_wrote = 0;
+ jb->samples = (char *)malloc(size*sizeof(char));
+
+ if (!jb->samples) {
+ chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
+ return NULL;
+ }
+
+ jb->ok = (char *)malloc(size*sizeof(char));
+
+ if (!jb->ok) {
+ chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
+ return NULL;
+ }
+
+ for(i=0; i<size; i++)
+ jb->ok[i]=0;
+
+ ast_mutex_init(&jb->mutexjb);
+
+ return jb;
+}
+
+/* frees the data and destroys the given jitterbuffer struct */
+void misdn_jb_destroy(struct misdn_jb *jb)
+{
+ ast_mutex_destroy(&jb->mutexjb);
+
+ free(jb->samples);
+ free(jb);
+}
+
+/* fills the jitterbuffer with len data returns < 0 if there was an
+ error (bufferoverflow). */
+int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
+{
+ int i, j, rp, wp;
+
+ if (!jb || ! data) return 0;
+
+ ast_mutex_lock (&jb->mutexjb);
+
+ wp=jb->wp;
+ rp=jb->rp;
+
+ for(i=0; i<len; i++)
+ {
+ jb->samples[wp]=data[i];
+ jb->ok[wp]=1;
+ wp = (wp!=jb->size-1 ? wp+1 : 0);
+
+ if(wp==jb->rp)
+ jb->state_full=1;
+ }
+
+ if(wp>=rp)
+ jb->state_buffer=wp-rp;
+ else
+ jb->state_buffer= jb->size-rp+wp;
+ chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
+
+ if(jb->state_full)
+ {
+ jb->wp=wp;
+
+ rp=wp;
+ for(j=0; j<jb->upper_threshold; j++)
+ rp = (rp!=0 ? rp-1 : jb->size-1);
+ jb->rp=rp;
+ jb->state_full=0;
+ jb->state_empty=1;
+
+ ast_mutex_unlock (&jb->mutexjb);
+
+ return -1;
+ }
+
+ if(!jb->state_empty)
+ {
+ jb->bytes_wrote+=len;
+ if(jb->bytes_wrote>=jb->upper_threshold)
+ {
+ jb->state_empty=1;
+ jb->bytes_wrote=0;
+ }
+ }
+ jb->wp=wp;
+
+ ast_mutex_unlock (&jb->mutexjb);
+
+ return 0;
+}
+
+/* gets len bytes out of the jitterbuffer if available, else only the
+available data is returned and the return value indicates the number
+of data. */
+int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
+{
+ int i, wp, rp, read=0;
+
+ ast_mutex_lock (&jb->mutexjb);
+
+ rp=jb->rp;
+ wp=jb->wp;
+
+ if(jb->state_empty)
+ {
+ for(i=0; i<len; i++)
+ {
+ if(wp==rp)
+ {
+ jb->rp=rp;
+ jb->state_empty=0;
+
+ ast_mutex_unlock (&jb->mutexjb);
+
+ return read;
+ }
+ else
+ {
+ if(jb->ok[rp]==1)
+ {
+ data[i]=jb->samples[rp];
+ jb->ok[rp]=0;
+ rp=(rp!=jb->size-1 ? rp+1 : 0);
+ read+=1;
+ }
+ }
+ }
+
+ if(wp >= rp)
+ jb->state_buffer=wp-rp;
+ else
+ jb->state_buffer= jb->size-rp+wp;
+ chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
+
+ jb->rp=rp;
+ }
+ else
+ chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
+
+ ast_mutex_unlock (&jb->mutexjb);
+
+ return read;
+}
+
+
+
+
+/*******************************************************/
+/*************** JITTERBUFFER END *********************/
+/*******************************************************/
+
+
+
+
+void chan_misdn_log(int level, int port, char *tmpl, ...)
+{
+ if (! ((0 <= port) && (port <= max_ports))) {
+ ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
+ port=0;
+ level=-1;
+ }
+
+ va_list ap;
+ char buf[1024];
+ char port_buf[8];
+ sprintf(port_buf,"P[%2d] ",port);
+
+ va_start(ap, tmpl);
+ vsnprintf( buf, 1023, tmpl, ap );
+ va_end(ap);
+
+ if (level == -1)
+ ast_log(LOG_WARNING, buf);
+
+ else if (misdn_debug_only[port] ?
+ (level==1 && misdn_debug[port]) || (level==misdn_debug[port])
+ : level <= misdn_debug[port]) {
+
+ ast_console_puts(port_buf);
+ ast_console_puts(buf);
+ }
+
+ if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
+ time_t tm = time(NULL);
+ char *tmp=ctime(&tm),*p;
+
+ FILE *fp= fopen(global_tracefile, "a+");
+
+ p=strchr(tmp,'\n');
+ if (p) *p=':';
+
+ if (!fp) {
+ ast_console_puts("Error opening Tracefile: [ ");
+ ast_console_puts(global_tracefile);
+ ast_console_puts(" ] ");
+
+ ast_console_puts(strerror(errno));
+ ast_console_puts("\n");
+ return ;
+ }
+
+ fputs(tmp,fp);
+ fputs(" ", fp);
+ fputs(port_buf,fp);
+ fputs(" ", fp);
+ fputs(buf, fp);
+
+ fclose(fp);
+ }
+}
+
+
diff --git a/channels/chan_misdn_config.c b/channels/chan_misdn_config.c
deleted file mode 100644
index 26598717c..000000000
--- a/channels/chan_misdn_config.c
+++ /dev/null
@@ -1,1083 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2005, Christian Richter
- *
- * Christian Richter <crich@beronet.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- *
- */
-
-/*!
- * \file
- *
- * \brief chan_misdn configuration management
- * \author Christian Richter <crich@beronet.com>
- *
- * \ingroup channel_drivers
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "chan_misdn_config.h"
-
-#include <asterisk/config.h>
-#include <asterisk/channel.h>
-#include <asterisk/logger.h>
-#include <asterisk/lock.h>
-#include <asterisk/strings.h>
-
-#include <asterisk/utils.h>
-#define AST_LOAD_CFG ast_config_load
-#define AST_DESTROY_CFG ast_config_destroy
-
-#define DEF_ECHOCANCEL 128
-#define DEF_ECHOTRAINING 1
-
-struct msn_list {
- char *msn;
- struct msn_list *next;
-};
-
-struct port_config {
- char *name;
- int *rxgain;
- int *txgain;
- int *te_choose_channel;
- char *context;
- char *language;
- char *callerid;
- char *method;
- int *dialplan;
- int *localdialplan;
- char *nationalprefix;
- char *internationalprefix;
- int *pres;
- int *always_immediate;
- int *immediate;
- int *hold_allowed;
- int *early_bconnect;
- int *use_callingpres;
- int *echocancel;
- int *echocancelwhenbridged;
- int *echotraining;
- struct msn_list *msn_list;
- ast_group_t *callgroup; /* Call group */
- ast_group_t *pickupgroup; /* Pickup group */
-};
-
-struct general_config {
- int *debug;
- char *tracefile;
- int *trace_calls;
- char *trace_dir;
- int *bridging;
- int *stop_tone_after_first_digit;
- int *append_digits2exten;
- int *l1_info_ok;
- int *clear_l3;
- int *dynamic_crypt;
- char *crypt_prefix;
- char *crypt_keys;
-};
-
-/* array of port configs, default is at position 0. */
-static struct port_config **port_cfg;
-/* max number of available ports, is set on init */
-static int max_ports;
-/* general config */
-static struct general_config *general_cfg;
-/* storing the ptp flag separated to save memory */
-static int *ptp;
-
-static ast_mutex_t config_mutex;
-
-
-static inline void misdn_cfg_lock (void) {
- ast_mutex_lock(&config_mutex);
-}
-
-static inline void misdn_cfg_unlock (void) {
- ast_mutex_unlock(&config_mutex);
-}
-
-static void free_msn_list (struct msn_list* iter) {
- if (iter->next)
- free_msn_list(iter->next);
- if (iter->msn)
- free(iter->msn);
- free(iter);
-}
-
-static void free_port_cfg (void) {
-
- struct port_config **free_list = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
-
- int i, j;
-
- for (i = 0; i < max_ports; i++) {
- if (port_cfg[i]) {
- for (j = 0; j < max_ports && free_list[j]; j++) {
- if (free_list[j] && free_list[j] == port_cfg[i])
- continue; /* already in list */
- free_list[j] = port_cfg[i];
- }
- }
- }
-
-#define FREE_ELEM(elem) ({ \
- if (free_list[i]->elem) \
- free(free_list[i]->elem); \
- })
-
- for (i = 0; i < max_ports; i++) {
- if (free_list[i]) {
- FREE_ELEM(name);
- FREE_ELEM(rxgain);
- FREE_ELEM(txgain);
- FREE_ELEM(te_choose_channel);
- FREE_ELEM(context);
- FREE_ELEM(language);
- FREE_ELEM(callerid);
- FREE_ELEM(method);
- FREE_ELEM(dialplan);
- FREE_ELEM(localdialplan);
- FREE_ELEM(nationalprefix);
- FREE_ELEM(internationalprefix);
- FREE_ELEM(pres);
- FREE_ELEM(always_immediate);
- FREE_ELEM(immediate);
- FREE_ELEM(hold_allowed);
- FREE_ELEM(early_bconnect);
- FREE_ELEM(use_callingpres);
- FREE_ELEM(echocancel);
- FREE_ELEM(echocancelwhenbridged);
- FREE_ELEM(echotraining);
- if (free_list[i]->msn_list)
- free_msn_list(free_list[i]->msn_list);
- FREE_ELEM(callgroup);
- FREE_ELEM(pickupgroup);
- free(free_list[i]);
- }
- }
- free(free_list);
-}
-
-static void free_general_cfg (void) {
-
-#define FREE_GEN_ELEM(elem) ({ \
- if (general_cfg->elem) \
- free(general_cfg->elem); \
- })
-
- FREE_GEN_ELEM(debug);
- FREE_GEN_ELEM(tracefile);
- FREE_GEN_ELEM(trace_calls);
- FREE_GEN_ELEM(trace_dir);
- FREE_GEN_ELEM(bridging);
- FREE_GEN_ELEM(stop_tone_after_first_digit);
- FREE_GEN_ELEM(append_digits2exten);
- FREE_GEN_ELEM(l1_info_ok);
- FREE_GEN_ELEM(clear_l3);
- FREE_GEN_ELEM(dynamic_crypt);
- FREE_GEN_ELEM(crypt_prefix);
- FREE_GEN_ELEM(crypt_keys);
-}
-
-#define GET_PORTCFG_STRCPY(item) ({ \
- char *temp; \
- if (port_cfg[port] && port_cfg[port]->item) \
- temp = port_cfg[port]->item; \
- else \
- temp = port_cfg[0]->item; \
- if (!temp || !memccpy((void *)buf, (void *)temp, '\0', bufsize)) \
- memset(buf, 0, 1); \
- })
-
-#define GET_GENCFG_STRCPY(item) ({ \
- if (general_cfg && general_cfg->item) { \
- if (!memccpy((void *)buf, (void *)general_cfg->item, '\0', bufsize)) \
- memset(buf, 0, 1); \
- } else \
- memset(buf, 0, 1); \
- })
-
-#define GET_PORTCFG_MEMCPY(item) ({ \
- typeof(port_cfg[0]->item) temp; \
- if (port_cfg[port] && port_cfg[port]->item) \
- temp = port_cfg[port]->item; \
- else \
- temp = port_cfg[0]->item; \
- if (temp) { \
- int l = sizeof(*temp); \
- if (l > bufsize) \
- memset(buf, 0, bufsize); \
- else \
- memcpy(buf, temp, l); \
- } else \
- memset(buf, 0, bufsize); \
- })
-
-#define GET_GENCFG_MEMCPY(item) ({ \
- if (general_cfg && general_cfg->item) { \
- typeof(general_cfg->item) temp = general_cfg->item; \
- int l = sizeof(*temp); \
- if (l > bufsize) \
- memset(buf, 0, bufsize); \
- else \
- memcpy(buf, temp, l); \
- } else \
- memset(buf, 0, bufsize); \
- })
-
-void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void *buf, int bufsize) {
-
- if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
- memset(buf, 0, bufsize);
- ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
- return;
- }
-
- misdn_cfg_lock();
-
- switch (elem) {
-
- /* port config elements */
-
- case MISDN_CFG_PTP: if (sizeof(ptp[port]) <= bufsize)
- memcpy(buf, &ptp[port], sizeof(ptp[port]));
- else
- buf = 0; /* error, should not happen */
- break;
- case MISDN_CFG_GROUPNAME: GET_PORTCFG_STRCPY(name);
- break;
- case MISDN_CFG_RXGAIN: GET_PORTCFG_MEMCPY(rxgain);
- break;
- case MISDN_CFG_TXGAIN: GET_PORTCFG_MEMCPY(txgain);
- break;
- case MISDN_CFG_TE_CHOOSE_CHANNEL:
- GET_PORTCFG_MEMCPY(te_choose_channel);
- break;
- case MISDN_CFG_CONTEXT: GET_PORTCFG_STRCPY(context);
- break;
- case MISDN_CFG_LANGUAGE: GET_PORTCFG_STRCPY(language);
- break;
- case MISDN_CFG_CALLERID: GET_PORTCFG_STRCPY(callerid);
- break;
- case MISDN_CFG_METHOD: GET_PORTCFG_STRCPY(method);
- break;
- case MISDN_CFG_DIALPLAN: GET_PORTCFG_MEMCPY(dialplan);
- break;
- case MISDN_CFG_LOCALDIALPLAN: GET_PORTCFG_MEMCPY(localdialplan);
- break;
- case MISDN_CFG_NATPREFIX: GET_PORTCFG_STRCPY(nationalprefix);
- break;
- case MISDN_CFG_INTERNATPREFIX:
- GET_PORTCFG_STRCPY(internationalprefix);
- break;
- case MISDN_CFG_PRES: GET_PORTCFG_MEMCPY(pres);
- break;
- case MISDN_CFG_ALWAYS_IMMEDIATE:
- GET_PORTCFG_MEMCPY(always_immediate);
- break;
- case MISDN_CFG_IMMEDIATE: GET_PORTCFG_MEMCPY(immediate);
- break;
- case MISDN_CFG_HOLD_ALLOWED:
- GET_PORTCFG_MEMCPY(hold_allowed);
- break;
- case MISDN_CFG_EARLY_BCONNECT:
- GET_PORTCFG_MEMCPY(early_bconnect);
- break;
- case MISDN_CFG_USE_CALLINGPRES:
- GET_PORTCFG_MEMCPY(use_callingpres);
- break;
- case MISDN_CFG_ECHOCANCEL:
- GET_PORTCFG_MEMCPY(echocancel );
- break;
- case MISDN_CFG_ECHOCANCELWHENBRIDGED:
- GET_PORTCFG_MEMCPY(echocancelwhenbridged);
- break;
- case MISDN_CFG_ECHOTRAINING:
- GET_PORTCFG_MEMCPY(echotraining);
- break;
- case MISDN_CFG_CALLGROUP: GET_PORTCFG_MEMCPY(callgroup);
- break;
- case MISDN_CFG_PICKUPGROUP: GET_PORTCFG_MEMCPY(pickupgroup);
- break;
-
- /* general config elements */
-
- case MISDN_GEN_DEBUG: GET_GENCFG_MEMCPY(debug);
- break;
- case MISDN_GEN_TRACEFILE: GET_GENCFG_STRCPY(tracefile);
- break;
- case MISDN_GEN_TRACE_CALLS: GET_GENCFG_MEMCPY(trace_calls);
- break;
- case MISDN_GEN_TRACE_DIR: GET_GENCFG_STRCPY(trace_dir);
- break;
- case MISDN_GEN_BRIDGING: GET_GENCFG_MEMCPY(bridging);
- break;
- case MISDN_GEN_STOP_TONE: GET_GENCFG_MEMCPY(stop_tone_after_first_digit);
- break;
- case MISDN_GEN_APPEND_DIGITS2EXTEN:
- GET_GENCFG_MEMCPY(append_digits2exten);
- break;
- case MISDN_GEN_L1_INFO_OK: GET_GENCFG_MEMCPY(l1_info_ok);
- break;
- case MISDN_GEN_CLEAR_L3: GET_GENCFG_MEMCPY(clear_l3);
- break;
- case MISDN_GEN_DYNAMIC_CRYPT: GET_GENCFG_MEMCPY(dynamic_crypt);
- break;
- case MISDN_GEN_CRYPT_PREFIX: GET_GENCFG_STRCPY(crypt_prefix);
- break;
- case MISDN_GEN_CRYPT_KEYS: GET_GENCFG_STRCPY(crypt_keys);
- break;
- default: memset(buf, 0, bufsize);
- }
-
- misdn_cfg_unlock();
-}
-
-int misdn_cfg_is_msn_valid (int port, char* msn) {
-
- if (!misdn_cfg_is_port_valid(port)) {
- ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
- return 0;
- }
-
- struct msn_list *iter;
-
- misdn_cfg_lock();
-
- if (port_cfg[port]->msn_list)
- iter = port_cfg[port]->msn_list;
- else
- iter = port_cfg[0]->msn_list;
- for (; iter; iter = iter->next)
- if (*(iter->msn) == '*' || !strcasecmp(iter->msn, msn)) {
- misdn_cfg_unlock();
- return 1;
- }
-
- misdn_cfg_unlock();
-
- return 0;
-}
-
-int misdn_cfg_is_port_valid (int port) {
-
- misdn_cfg_lock();
-
- if (port < 1 || port > max_ports) {
- misdn_cfg_unlock();
- return 0;
- }
-
- int valid = (port_cfg[port] != NULL);
-
- misdn_cfg_unlock();
-
- return valid;
-}
-
-int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth) {
-
- int i, re = 0;
- char *method = NULL;
-
- misdn_cfg_lock();
-
- for (i = 0; i < max_ports; i++) {
- if (port_cfg[i]) {
- if (!strcasecmp(port_cfg[i]->name, group))
- method = port_cfg[i]->method ? port_cfg[i]->method : port_cfg[0]->method;
- }
- }
-
- if (method) {
- switch (meth) {
- case METHOD_STANDARD: re = !strcasecmp(method, "standard");
- break;
- case METHOD_ROUND_ROBIN: re = !strcasecmp(method, "round_robin");
- break;
- }
- }
-
- misdn_cfg_unlock();
-
- return re;
-}
-
-void misdn_cfg_get_ports_string (char *ports) {
- *ports = 0;
- char tmp[16];
- int l;
-
- misdn_cfg_lock();
-
- int i = 1;
- for (; i <= max_ports; i++) {
- if (port_cfg[i]) {
- if (ptp[i])
- sprintf(tmp, "%dptp,", i);
- else
- sprintf(tmp, "%d,", i);
- strcat(ports, tmp);
- }
- }
-
- misdn_cfg_unlock();
-
- if ((l = strlen(ports)))
- ports[l-1] = 0;
-}
-
-#define GET_CFG_STRING(typestr, type) ({ \
- if (port_cfg[port] && port_cfg[port]->type) \
- snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[port]->type); \
- else \
- snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[0]->type); \
- }) \
-
-#define GET_GEN_STRING(typestr, type) ({ \
- snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? general_cfg->type : "not set"); \
- }) \
-
-#define GET_CFG_INT(typestr, type) ({ \
- if (port_cfg[port] && port_cfg[port]->type) \
- snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[port]->type); \
- else \
- snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[0]->type); \
- }) \
-
-#define GET_GEN_INT(typestr, type) ({ \
- snprintf(buf, bufsize, "%s " #typestr ": %d", begin, general_cfg->type ? *general_cfg->type : 0); \
- }) \
-
-#define GET_CFG_BOOL(typestr, type, yes, no) ({ \
- int bool; \
- if (port_cfg[port] && port_cfg[port]->type) \
- bool = *port_cfg[port]->type; \
- else \
- bool = *port_cfg[0]->type; \
- snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
- }) \
-
-#define GET_CFG_HYBRID(typestr, type, yes, no) ({ \
- int bool; \
- if (port_cfg[port] && port_cfg[port]->type) \
- bool = *port_cfg[port]->type; \
- else \
- bool = *port_cfg[0]->type; \
- if (bool == 1 || bool == 0) \
- snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
- else \
- snprintf(buf, bufsize, "%s " #typestr ": %d", begin, bool); \
- }) \
-
-#define GET_GEN_BOOL(typestr, type, yes, no) ({ \
- snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? (*general_cfg->type ? #yes : #no) : "not set"); \
- }) \
-
-#define GET_CFG_AST_GROUP_T(typestr, type) ({ \
- ast_group_t *tmp; \
- if (port_cfg[port] && port_cfg[port]->type) \
- tmp = port_cfg[port]->type; \
- else \
- tmp = port_cfg[0]->type; \
- if (tmp) { \
- char tmpbuf[256]; \
- snprintf(buf, bufsize, "%s " #typestr ": %s", begin, ast_print_group(tmpbuf, sizeof(tmpbuf), *tmp)); \
- } else \
- snprintf(buf, bufsize, "%s " #typestr ": %s", begin, "none"); \
- }) \
-
-void misdn_cfg_get_config_string(int port, enum misdn_cfg_elements elem, char* buf, int bufsize) {
-
- if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
- *buf = 0;
- ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
- return;
- }
-
- char begin[] = " -> ";
-
- misdn_cfg_lock();
-
- switch (elem) {
-
- case MISDN_CFG_PTP: snprintf(buf, bufsize, "%s PTP: %s", begin, ptp[port] ? "yes" : "no");
- break;
- case MISDN_CFG_GROUPNAME: GET_CFG_STRING(GROUPNAME, name);
- break;
- case MISDN_CFG_RXGAIN: GET_CFG_INT(RXGAIN, rxgain);
- break;
- case MISDN_CFG_TXGAIN: GET_CFG_INT(TXGAIN, txgain);
- break;
- case MISDN_CFG_TE_CHOOSE_CHANNEL:
- GET_CFG_BOOL(TE_CHOOSE_CHANNEL, te_choose_channel, yes, no);
- break;
- case MISDN_CFG_CONTEXT: GET_CFG_STRING(CONTEXT, context);
- break;
- case MISDN_CFG_LANGUAGE: GET_CFG_STRING(LANGUAGE, language);
- break;
- case MISDN_CFG_CALLERID: GET_CFG_STRING(CALLERID, callerid);
- break;
- case MISDN_CFG_METHOD: GET_CFG_STRING(METHOD, method);
- break;
- case MISDN_CFG_DIALPLAN: GET_CFG_INT(DIALPLAN, dialplan);
- break;
- case MISDN_CFG_LOCALDIALPLAN: GET_CFG_INT(LOCALDIALPLAN, localdialplan);
- break;
- case MISDN_CFG_NATPREFIX: GET_CFG_STRING(NATIONALPREFIX, nationalprefix);
- break;
- case MISDN_CFG_INTERNATPREFIX:
- GET_CFG_STRING(INTERNATIONALPREFIX, internationalprefix);
- break;
- case MISDN_CFG_PRES: GET_CFG_BOOL(PRESENTATION, pres, allowed, not_screened);
- break;
- case MISDN_CFG_ALWAYS_IMMEDIATE:
- GET_CFG_BOOL(ALWAYS_IMMEDIATE, always_immediate, yes, no);
- break;
- case MISDN_CFG_IMMEDIATE: GET_CFG_BOOL(IMMEDIATE, immediate, yes, no);
- break;
- case MISDN_CFG_HOLD_ALLOWED:
- GET_CFG_BOOL(HOLD_ALLOWED, hold_allowed, yes, no);
- break;
- case MISDN_CFG_EARLY_BCONNECT:
- GET_CFG_BOOL(EARLY_BCONNECT, early_bconnect, yes, no);
- break;
- case MISDN_CFG_USE_CALLINGPRES:
- GET_CFG_BOOL(USE_CALLINGPRES, use_callingpres, yes, no);
- break;
- case MISDN_CFG_ECHOCANCEL: GET_CFG_HYBRID(ECHOCANCEL, echocancel, yes, no);
- break;
- case MISDN_CFG_ECHOCANCELWHENBRIDGED:
- GET_CFG_BOOL(ECHOCANCELWHENBRIDGED, echocancelwhenbridged, yes, no);
- break;
- case MISDN_CFG_ECHOTRAINING:
- GET_CFG_HYBRID(ECHOTRAINING, echotraining, yes, no);
- break;
- case MISDN_CFG_CALLGROUP: GET_CFG_AST_GROUP_T(CALLINGGROUP, callgroup);
- break;
- case MISDN_CFG_PICKUPGROUP: GET_CFG_AST_GROUP_T(PICKUPGROUP, pickupgroup);
- break;
- case MISDN_CFG_MSNS: {
- char tmpbuffer[BUFFERSIZE];
- tmpbuffer[0] = 0;
- struct msn_list *iter;
- if (port_cfg[port]->msn_list)
- iter = port_cfg[port]->msn_list;
- else
- iter = port_cfg[0]->msn_list;
- if (iter) {
- for (; iter; iter = iter->next)
- sprintf(tmpbuffer, "%s%s, ", tmpbuffer, iter->msn);
- tmpbuffer[strlen(tmpbuffer)-2] = 0;
- }
- snprintf(buf, bufsize, "%s MSNs: %s", begin, *tmpbuffer ? tmpbuffer : "none"); \
- }
- break;
-
- /* general config elements */
-
- case MISDN_GEN_DEBUG: GET_GEN_INT(DEBUG_LEVEL, debug);
- break;
- case MISDN_GEN_TRACEFILE: GET_GEN_STRING(TRACEFILE, tracefile);
- break;
- case MISDN_GEN_TRACE_CALLS: GET_GEN_BOOL(TRACE_CALLS, trace_calls, true, false);
- break;
- case MISDN_GEN_TRACE_DIR: GET_GEN_STRING(TRACE_DIR, trace_dir);
- break;
- case MISDN_GEN_BRIDGING: GET_GEN_BOOL(BRIDGING, bridging, yes, no);
- break;
- case MISDN_GEN_STOP_TONE: GET_GEN_BOOL(STOP_TONE_AFTER_FIRST_DIGIT, stop_tone_after_first_digit, yes, no);
- break;
- case MISDN_GEN_APPEND_DIGITS2EXTEN:
- GET_GEN_BOOL(APPEND_DIGITS2EXTEN, append_digits2exten, yes, no);
- break;
- case MISDN_GEN_L1_INFO_OK: GET_GEN_BOOL(L1_INFO_OK, l1_info_ok, yes, no);
- break;
- case MISDN_GEN_CLEAR_L3: GET_GEN_BOOL(CLEAR_L3, clear_l3, yes, no);
- break;
- case MISDN_GEN_DYNAMIC_CRYPT:
- GET_GEN_BOOL(DYNAMIC_CRYPT,dynamic_crypt, yes, no);
- break;
- case MISDN_GEN_CRYPT_PREFIX:
- GET_GEN_STRING(CRYPT_PREFIX, crypt_prefix);
- break;
- case MISDN_GEN_CRYPT_KEYS: GET_GEN_STRING(CRYPT_KEYS, crypt_keys);
- break;
-
- default: *buf = 0;
- break;
- }
-
- misdn_cfg_unlock();
-}
-
-int misdn_cfg_get_next_port (int port) {
-
- misdn_cfg_lock();
-
- for (port++; port <= max_ports; port++) {
- if (port_cfg[port]) {
- misdn_cfg_unlock();
- return port;
- }
- }
-
- misdn_cfg_unlock();
-
- return -1;
-}
-
-int misdn_cfg_get_next_port_spin (int port) {
-
- int ret = misdn_cfg_get_next_port(port);
-
- if (ret > 0)
- return ret;
-
- return misdn_cfg_get_next_port(0);
-}
-
-#define PARSE_GEN_INT(item) ({ \
- if (!strcasecmp(v->name, #item)) { \
- int temp; \
- if (!sscanf(v->value, "%d", &temp)) { \
- ast_log(LOG_WARNING, "Value \"%s\" for \"" #item "\" (generals section) invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", v->value); \
- } else { \
- general_cfg->item = (int *)malloc(sizeof(int)); \
- memcpy(general_cfg->item, &temp, sizeof(int)); \
- } \
- continue; \
- } \
- }) \
-
-#define PARSE_GEN_BOOL(item) ({ \
- if (!strcasecmp(v->name, #item)) { \
- general_cfg->item = (int *)malloc(sizeof(int)); \
- *(general_cfg->item) = ast_true(v->value)?1:0; \
- continue; \
- } \
- })
-
-#define PARSE_GEN_STR(item) ({ \
- if (!strcasecmp(v->name, #item)) { \
- int l = strlen(v->value); \
- if (l) { \
- general_cfg->item = (char *)calloc(l+1, sizeof(char)); \
- strncpy(general_cfg->item,v->value, l); \
- } \
- continue; \
- } \
- })
-
-static void build_general_config(struct ast_variable *v) {
-
- if (!v)
- return;
-
- for (; v; v = v->next) {
-
- PARSE_GEN_INT(debug);
- PARSE_GEN_STR(tracefile);
- PARSE_GEN_BOOL(trace_calls);
- PARSE_GEN_STR(trace_dir);
- PARSE_GEN_BOOL(bridging);
- PARSE_GEN_BOOL(stop_tone_after_first_digit);
- PARSE_GEN_BOOL(append_digits2exten);
- PARSE_GEN_BOOL(l1_info_ok);
- PARSE_GEN_BOOL(clear_l3);
- PARSE_GEN_BOOL(dynamic_crypt);
- PARSE_GEN_STR(crypt_prefix);
- PARSE_GEN_STR(crypt_keys);
-
- }
-}
-
-#define PARSE_CFG_HYBRID(item, def) ({ \
- if (!strcasecmp(v->name, #item)) { \
- new->item = (int *)malloc(sizeof(int)); \
- if (!sscanf(v->value, "%d", new->item)) { \
- if (ast_true(v->value)) \
- *new->item = def; \
- else \
- *new->item = 0; \
- } \
- continue; \
- } \
- }) \
-
-#define PARSE_CFG_INT(item) ({ \
- if (!strcasecmp(v->name, #item)) { \
- new->item = (int *)malloc(sizeof(int)); \
- if (!sscanf(v->value, "%d", new->item)) { \
- ast_log(LOG_WARNING, "Value \"%s\" for \"" #item "\" of group \"%s\" invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", v->value, cat); \
- free(new->item); \
- new->item = NULL; \
- } \
- continue; \
- } \
- }) \
-
-#define PARSE_CFG_BOOL(item) ({ \
- if (!strcasecmp(v->name, #item)) { \
- new->item = (int *)malloc(sizeof(int)); \
- *(new->item) = ast_true(v->value)?1:0; \
- continue; \
- } \
- })
-
-#define PARSE_CFG_STR(item) ({ \
- if (!strcasecmp(v->name, #item)) { \
- int l = strlen(v->value); \
- if (l) { \
- new->item = (char *)calloc(l+1, sizeof(char)); \
- strncpy(new->item,v->value,l); \
- } \
- continue; \
- } \
- })
-
-static void build_port_config(struct ast_variable *v, char *cat) {
- if (!v || !cat)
- return;
-
- int cfg_for_ports[max_ports + 1];
- int i = 0;
- for (; i < (max_ports + 1); i++) {
- cfg_for_ports[i] = 0;
- }
-
- /* we store the default config at position 0 */
- if (!strcasecmp(cat, "default")) {
- cfg_for_ports[0] = 1;
- }
-
- struct port_config* new = (struct port_config *)calloc(1, sizeof(struct port_config));
-
- {
- int l = strlen(cat);
- new->name = (char *)calloc(l+1, sizeof(char));
- strncpy(new->name, cat, l);
- }
-
- for (; v; v=v->next) {
- if (!strcasecmp(v->name, "ports")) {
- /* TODO check for value not beeing set, like PORTS= */
- char *iter;
- char *value = v->value;
- while ((iter = strchr(value, ',')) != NULL) {
- *iter = 0;
- /* strip spaces */
- while (*value && *value == ' ') {
- value++;
- }
- /* TODO check for char not 0-9 */
-
- if (*value){
- int p = atoi(value);
- if (p <= max_ports && p > 0) {
- cfg_for_ports[p] = 1;
- if (strstr(value, "ptp"))
- ptp[p] = 1;
- } else
- ast_log(LOG_WARNING, "Port value \"%s\" of group %s invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", value, cat);
- value = ++iter;
- }
- }
- /* the remaining or the only one */
- /* strip spaces */
- while (*value && *value == ' ') {
- value++;
- }
- /* TODO check for char not 0-9 */
- if (*value) {
- int p = atoi(value);
- if (p <= max_ports && p > 0) {
- cfg_for_ports[p] = 1;
- if (strstr(value, "ptp"))
- ptp[p] = 1;
- } else
- ast_log(LOG_WARNING, "Port value \"%s\" of group %s invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", value, cat);
- }
- continue;
- }
- PARSE_CFG_STR(context);
- PARSE_CFG_INT(dialplan);
- PARSE_CFG_INT(localdialplan);
- PARSE_CFG_STR(nationalprefix);
- PARSE_CFG_STR(internationalprefix);
- PARSE_CFG_STR(language);
- if (!strcasecmp(v->name, "presentation")) {
- if (v->value && strlen(v->value)) {
- new->pres = (int *)malloc(sizeof(int));
- if (!strcasecmp(v->value, "allowed")) {
- *(new->pres) = 1;
- }
- /* TODO: i assume if it is not "allowed", it is "not_screened" */
- else {
- *(new->pres) = 0;
- }
- }
- continue;
- }
- PARSE_CFG_INT(rxgain);
- PARSE_CFG_INT(txgain);
- PARSE_CFG_BOOL(te_choose_channel);
- PARSE_CFG_BOOL(immediate);
- PARSE_CFG_BOOL(always_immediate);
- PARSE_CFG_BOOL(hold_allowed);
- PARSE_CFG_BOOL(early_bconnect);
- PARSE_CFG_BOOL(use_callingpres);
- PARSE_CFG_HYBRID(echocancel, DEF_ECHOCANCEL);
- PARSE_CFG_BOOL(echocancelwhenbridged);
- PARSE_CFG_HYBRID(echotraining, DEF_ECHOTRAINING);
- PARSE_CFG_STR(callerid);
- PARSE_CFG_STR(method);
- if (!strcasecmp(v->name, "msns")) {
- /* TODO check for value not beeing set, like msns= */
- char *iter;
- char *value = v->value;
-
- while ((iter = strchr(value, ',')) != NULL) {
- *iter = 0;
- /* strip spaces */
- while (*value && *value == ' ') {
- value++;
- }
- /* TODO check for char not 0-9 */
- if (*value){
- int l = strlen(value);
- if (l) {
- struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
- ml->msn = (char *)calloc(l+1, sizeof(char));
- strncpy(ml->msn,value,l);
- ml->next = new->msn_list;
- new->msn_list = ml;
- }
- value = ++iter;
- }
- }
- /* the remaining or the only one */
- /* strip spaces */
- while (*value && *value == ' ') {
- value++;
- }
- /* TODO check for char not 0-9 */
- if (*value) {
- int l = strlen(value);
- if (l) {
- struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
- ml->msn = (char *)calloc(l+1, sizeof(char));
- strncpy(ml->msn,value,l);
- ml->next = new->msn_list;
- new->msn_list = ml;
- }
- }
- continue;
- }
- if (!strcasecmp(v->name, "callgroup")) {
- new->callgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
- *(new->callgroup)=ast_get_group(v->value);
- continue;
- }
- if (!strcasecmp(v->name, "pickupgroup")) {
- new->pickupgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
- *(new->pickupgroup)=ast_get_group(v->value);
- continue;
- }
- }
- /* store the new config in our array of port configs */
- for (i = 0; i < (max_ports + 1); i++) {
- if (cfg_for_ports[i])
- port_cfg[i] = new;
- }
-}
-
-
-static void fill_defaults (void) {
-
- /* general defaults */
- if (!general_cfg->debug)
- general_cfg->debug = (int*)calloc(1, sizeof(int));
- if (!general_cfg->trace_calls)
- general_cfg->trace_calls = (int*)calloc(1, sizeof(int));
- if (!general_cfg->trace_dir) {
- general_cfg->trace_dir = (char *)malloc(10 * sizeof(char));
- sprintf(general_cfg->trace_dir, "/var/log/");
- }
- if (!general_cfg->bridging) {
- general_cfg->bridging = (int*)malloc(sizeof(int));
- *general_cfg->bridging = 1;
- }
- if (!general_cfg->stop_tone_after_first_digit) {
- general_cfg->stop_tone_after_first_digit = (int*)malloc(sizeof(int));
- *general_cfg->stop_tone_after_first_digit = 1;
- }
- if (!general_cfg->append_digits2exten) {
- general_cfg->append_digits2exten = (int*)malloc(sizeof(int));
- *general_cfg->append_digits2exten = 1;
- }
- if (!general_cfg->l1_info_ok) {
- general_cfg->l1_info_ok = (int*)malloc(sizeof(int));
- *general_cfg->l1_info_ok = 1;
- }
- if (!general_cfg->clear_l3)
- general_cfg->clear_l3 =(int*)calloc(1, sizeof(int));
- if (!general_cfg->dynamic_crypt)
- general_cfg->dynamic_crypt = (int*)calloc(1, sizeof(int));
-
- /* defaults for default port config */
- if (!port_cfg[0])
- port_cfg[0] = (struct port_config*)calloc(1, sizeof(struct port_config));
- if (!port_cfg[0]->name) {
- port_cfg[0]->name = (char *)malloc(8 * sizeof(char));
- sprintf(port_cfg[0]->name, "default");
- }
- if (!port_cfg[0]->rxgain)
- port_cfg[0]->rxgain = (int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->txgain)
- port_cfg[0]->txgain = (int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->te_choose_channel)
- port_cfg[0]->te_choose_channel = (int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->context) {
- port_cfg[0]->context = (char *)malloc(8 * sizeof(char));
- sprintf(port_cfg[0]->context, "default");
- }
- if (!port_cfg[0]->language) {
- port_cfg[0]->language = (char *)malloc(3 * sizeof(char));
- sprintf(port_cfg[0]->language, "en");
- }
- if (!port_cfg[0]->callerid)
- port_cfg[0]->callerid = (char *)calloc(1, sizeof(char));
- if (!port_cfg[0]->method) {
- port_cfg[0]->method = (char *)malloc(9 * sizeof(char));
- sprintf(port_cfg[0]->method, "standard");
- }
- if (!port_cfg[0]->dialplan)
- port_cfg[0]->dialplan = (int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->localdialplan)
- port_cfg[0]->localdialplan = (int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->nationalprefix) {
- port_cfg[0]->nationalprefix = (char *)malloc(2 * sizeof(char));
- sprintf(port_cfg[0]->nationalprefix, "0");
- }
- if (!port_cfg[0]->internationalprefix) {
- port_cfg[0]->internationalprefix = (char *)malloc(3 * sizeof(char));
- sprintf(port_cfg[0]->internationalprefix, "00");
- }
- if (!port_cfg[0]->pres) {
- port_cfg[0]->pres = (int *)malloc(sizeof(int));
- *port_cfg[0]->pres = 1;
- }
- if (!port_cfg[0]->always_immediate)
- port_cfg[0]->always_immediate = (int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->immediate)
- port_cfg[0]->immediate = (int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->hold_allowed)
- port_cfg[0]->hold_allowed = (int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->early_bconnect) {
- port_cfg[0]->early_bconnect = (int *)malloc(sizeof(int));
- *port_cfg[0]->early_bconnect = 1;
- }
- if (!port_cfg[0]->echocancel)
- port_cfg[0]->echocancel=(int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->echocancelwhenbridged)
- port_cfg[0]->echocancelwhenbridged=(int *)calloc(1, sizeof(int));
- if (!port_cfg[0]->echotraining) {
- port_cfg[0]->echotraining=(int *)malloc(sizeof(int));
- *port_cfg[0]->echotraining = 1;
- }
- if (!port_cfg[0]->use_callingpres) {
- port_cfg[0]->use_callingpres = (int *)malloc(sizeof(int));
- *port_cfg[0]->use_callingpres = 1;
- }
- if (!port_cfg[0]->msn_list) {
- port_cfg[0]->msn_list = (struct msn_list *)malloc(sizeof(struct msn_list));
- port_cfg[0]->msn_list->next = NULL;
- port_cfg[0]->msn_list->msn = (char *)calloc(2, sizeof(char));
- *(port_cfg[0]->msn_list->msn) = '*';
- }
-}
-
-void misdn_cfg_reload (void) {
- misdn_cfg_init (0);
-}
-
-void misdn_cfg_destroy (void) {
-
- misdn_cfg_lock();
-
- free_port_cfg();
- free_general_cfg();
-
- free(port_cfg);
- free(general_cfg);
- free(ptp);
-
- misdn_cfg_unlock();
- ast_mutex_destroy(&config_mutex);
-}
-
-void misdn_cfg_init (int this_max_ports)
-{
- char config[]="misdn.conf";
-
- struct ast_config *cfg;
- cfg = AST_LOAD_CFG(config);
- if (!cfg) {
- ast_log(LOG_WARNING,"no misdn.conf ?\n");
- return;
- }
-
- misdn_cfg_lock();
-
- if (this_max_ports) {
- /* this is the first run */
- max_ports = this_max_ports;
- port_cfg = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
- general_cfg = (struct general_config*)calloc(1, sizeof(struct general_config));
- ptp = (int *)calloc(max_ports + 1, sizeof(int));
- }
- else {
- free_port_cfg();
- free_general_cfg();
- port_cfg = memset(port_cfg, 0, sizeof(struct port_config *) * (max_ports + 1));
- general_cfg = memset(general_cfg, 0, sizeof(struct general_config));
- ptp = memset(ptp, 0, sizeof(int) * (max_ports + 1));
- }
-
- char *cat;
- cat = ast_category_browse(cfg, NULL);
-
- while(cat) {
- struct ast_variable *v=ast_variable_browse(cfg,cat);
- if (!strcasecmp(cat,"general")) {
- build_general_config (v);
- } else {
- build_port_config (v, cat);
- }
- cat=ast_category_browse(cfg,cat);
- }
-
- fill_defaults();
-
- misdn_cfg_unlock();
-
- AST_DESTROY_CFG(cfg);
-}
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 *)(&centrex[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, &centrex[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 *)(&centrex[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, &centrex[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;
-}
diff --git a/channels/misdn_config.c b/channels/misdn_config.c
new file mode 100644
index 000000000..7c019dca0
--- /dev/null
+++ b/channels/misdn_config.c
@@ -0,0 +1,784 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2005, Christian Richter
+ *
+ * Christian Richter <crich@beronet.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ *
+ */
+
+/*!
+ * \file
+ *
+ * \brief chan_misdn configuration management
+ * \author Christian Richter <crich@beronet.com>
+ *
+ * \ingroup channel_drivers
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "chan_misdn_config.h"
+
+#include <asterisk/config.h>
+#include <asterisk/channel.h>
+#include <asterisk/logger.h>
+#include <asterisk/lock.h>
+#include <asterisk/pbx.h>
+#include <asterisk/strings.h>
+#include <asterisk/utils.h>
+
+#define AST_LOAD_CFG ast_config_load
+#define AST_DESTROY_CFG ast_config_destroy
+
+#define NO_DEFAULT "<>"
+#define NONE 0
+
+#define GEN_CFG 1
+#define PORT_CFG 2
+#define NUM_GEN_ELEMENTS (sizeof(gen_spec) / sizeof(struct misdn_cfg_spec))
+#define NUM_PORT_ELEMENTS (sizeof(port_spec) / sizeof(struct misdn_cfg_spec))
+
+enum misdn_cfg_type {
+ MISDN_CTYPE_STR,
+ MISDN_CTYPE_INT,
+ MISDN_CTYPE_BOOL,
+ MISDN_CTYPE_BOOLINT,
+ MISDN_CTYPE_MSNLIST,
+ MISDN_CTYPE_ASTGROUP
+};
+
+struct msn_list {
+ char *msn;
+ struct msn_list *next;
+};
+
+union misdn_cfg_pt {
+ char *str;
+ int *num;
+ struct msn_list *ml;
+ ast_group_t *grp;
+ void *any;
+};
+
+struct misdn_cfg_spec {
+ char name[BUFFERSIZE];
+ enum misdn_cfg_elements elem;
+ enum misdn_cfg_type type;
+ char def[BUFFERSIZE];
+ int boolint_def;
+};
+
+static const struct misdn_cfg_spec port_spec[] = {
+ { "name", MISDN_CFG_GROUPNAME, MISDN_CTYPE_STR, "default", NONE },
+ { "allowed_bearers", MISDN_CFG_ALLOWED_BEARERS, MISDN_CTYPE_STR, "all", NONE },
+ { "rxgain", MISDN_CFG_RXGAIN, MISDN_CTYPE_INT, "0", NONE },
+ { "txgain", MISDN_CFG_TXGAIN, MISDN_CTYPE_INT, "0", NONE },
+ { "te_choose_channel", MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CTYPE_BOOL, "no", NONE },
+ { "far_alerting", MISDN_CFG_FAR_ALERTING, MISDN_CTYPE_BOOL, "no", NONE },
+ { "pmp_l1_check", MISDN_CFG_PMP_L1_CHECK, MISDN_CTYPE_BOOL, "yes", NONE },
+ { "block_on_alarm", MISDN_CFG_ALARM_BLOCK, MISDN_CTYPE_BOOL, "yes", NONE },
+ { "hdlc", MISDN_CFG_HDLC, MISDN_CTYPE_BOOL, "no", NONE },
+ { "context", MISDN_CFG_CONTEXT, MISDN_CTYPE_STR, "default", NONE },
+ { "language", MISDN_CFG_LANGUAGE, MISDN_CTYPE_STR, "en", NONE },
+ { "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE },
+ { "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE },
+ { "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE },
+ { "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE },
+ { "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
+ { "cpndialplan", MISDN_CFG_CPNDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
+ { "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE },
+ { "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE },
+ { "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE },
+ { "screen", MISDN_CFG_SCREEN, MISDN_CTYPE_INT, "-1", NONE },
+ { "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
+ { "nodialtone", MISDN_CFG_NODIALTONE, MISDN_CTYPE_BOOL, "no", NONE },
+ { "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
+ { "senddtmf", MISDN_CFG_SENDDTMF, MISDN_CTYPE_BOOL, "no", NONE },
+ { "hold_allowed", MISDN_CFG_HOLD_ALLOWED, MISDN_CTYPE_BOOL, "no", NONE },
+ { "early_bconnect", MISDN_CFG_EARLY_BCONNECT, MISDN_CTYPE_BOOL, "yes", NONE },
+ { "incoming_early_audio", MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CTYPE_BOOL, "no", NONE },
+ { "echocancel", MISDN_CFG_ECHOCANCEL, MISDN_CTYPE_BOOLINT, "0", 128 },
+ { "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE },
+ { "jitterbuffer", MISDN_CFG_JITTERBUFFER, MISDN_CTYPE_INT, "4000", NONE },
+ { "jitterbuffer_upper_threshold", MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CTYPE_INT, "0", NONE },
+ { "callgroup", MISDN_CFG_CALLGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
+ { "pickupgroup", MISDN_CFG_PICKUPGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
+ { "msns", MISDN_CFG_MSNS, MISDN_CTYPE_MSNLIST, NO_DEFAULT, NONE }
+};
+
+static const struct misdn_cfg_spec gen_spec[] = {
+ { "debug", MISDN_GEN_DEBUG, MISDN_CTYPE_INT, "0", NONE },
+ { "misdn_init", MISDN_GEN_MISDN_INIT, MISDN_CTYPE_STR, "/etc/misdn-init.conf", NONE },
+ { "tracefile", MISDN_GEN_TRACEFILE, MISDN_CTYPE_STR, "/var/log/asterisk/misdn.log", NONE },
+ { "bridging", MISDN_GEN_BRIDGING, MISDN_CTYPE_BOOL, "yes", NONE },
+ { "stop_tone_after_first_digit", MISDN_GEN_STOP_TONE, MISDN_CTYPE_BOOL, "yes", NONE },
+ { "append_digits2exten", MISDN_GEN_APPEND_DIGITS2EXTEN, MISDN_CTYPE_BOOL, "yes", NONE },
+ { "dynamic_crypt", MISDN_GEN_DYNAMIC_CRYPT, MISDN_CTYPE_BOOL, "no", NONE },
+ { "crypt_prefix", MISDN_GEN_CRYPT_PREFIX, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
+ { "crypt_keys", MISDN_GEN_CRYPT_KEYS, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
+ { "ntdebugflags", MISDN_GEN_NTDEBUGFLAGS, MISDN_CTYPE_INT, "0", NONE },
+ { "ntdebugfile", MISDN_GEN_NTDEBUGFILE, MISDN_CTYPE_STR, "/var/log/misdn-nt.log", NONE }
+};
+
+/* array of port configs, default is at position 0. */
+static union misdn_cfg_pt **port_cfg;
+/* max number of available ports, is set on init */
+static int max_ports;
+/* general config */
+static union misdn_cfg_pt *general_cfg;
+/* storing the ptp flag separated to save memory */
+static int *ptp;
+/* maps enum config elements to array positions */
+static int *map;
+
+static ast_mutex_t config_mutex;
+
+#define CLI_ERROR(name, value, section) ({ \
+ ast_log(LOG_WARNING, "misdn.conf: \"%s=%s\" (section: %s) invalid or out of range. " \
+ "Please edit your misdn.conf and then do a \"misdn reload\".\n", name, value, section); \
+})
+
+static void _enum_array_map (void)
+{
+ int i, j;
+
+ for (i = MISDN_CFG_FIRST + 1; i < MISDN_CFG_LAST; ++i) {
+ if (i == MISDN_CFG_PTP)
+ continue;
+ for (j = 0; j < NUM_PORT_ELEMENTS; ++j) {
+ if (port_spec[j].elem == i) {
+ map[i] = j;
+ break;
+ }
+ }
+ }
+ for (i = MISDN_GEN_FIRST + 1; i < MISDN_GEN_LAST; ++i) {
+ for (j = 0; j < NUM_GEN_ELEMENTS; ++j) {
+ if (gen_spec[j].elem == i) {
+ map[i] = j;
+ break;
+ }
+ }
+ }
+}
+
+static int get_cfg_position (char *name, int type)
+{
+ int i;
+
+ switch (type) {
+ case PORT_CFG:
+ for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
+ if (!strcasecmp(name, port_spec[i].name))
+ return i;
+ }
+ break;
+ case GEN_CFG:
+ for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
+ if (!strcasecmp(name, gen_spec[i].name))
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static inline void misdn_cfg_lock (void)
+{
+ ast_mutex_lock(&config_mutex);
+}
+
+static inline void misdn_cfg_unlock (void)
+{
+ ast_mutex_unlock(&config_mutex);
+}
+
+static void _free_msn_list (struct msn_list* iter)
+{
+ if (iter->next)
+ _free_msn_list(iter->next);
+ if (iter->msn)
+ free(iter->msn);
+ free(iter);
+}
+
+static void _free_port_cfg (void)
+{
+ int i, j;
+ int gn = map[MISDN_CFG_GROUPNAME];
+ union misdn_cfg_pt* free_list[max_ports + 2];
+
+ memset(free_list, 0, sizeof(free_list));
+ free_list[0] = port_cfg[0];
+ for (i = 1; i <= max_ports; ++i) {
+ if (port_cfg[i][gn].str) {
+ /* we always have a groupname in the non-default case, so this is fine */
+ for (j = 1; j <= max_ports; ++j) {
+ if (free_list[j] && free_list[j][gn].str == port_cfg[i][gn].str)
+ break;
+ else if (!free_list[j]) {
+ free_list[j] = port_cfg[i];
+ break;
+ }
+ }
+ }
+ }
+ for (j = 0; free_list[j]; ++j) {
+ for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
+ if (free_list[j][i].any) {
+ if (port_spec[i].type == MISDN_CTYPE_MSNLIST)
+ _free_msn_list(free_list[j][i].ml);
+ else
+ free(free_list[j][i].any);
+ }
+ }
+ }
+}
+
+static void _free_general_cfg (void)
+{
+ int i;
+
+ for (i = 0; i < NUM_GEN_ELEMENTS; i++)
+ if (general_cfg[i].any)
+ free(general_cfg[i].any);
+}
+
+void misdn_cfg_get (int port, enum misdn_cfg_elements elem, void *buf, int bufsize)
+{
+ int place;
+
+ if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
+ memset(buf, 0, bufsize);
+ ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
+ return;
+ }
+
+ misdn_cfg_lock();
+ if (elem == MISDN_CFG_PTP) {
+ if (!memcpy(buf, &ptp[port], (bufsize > ptp[port]) ? sizeof(ptp[port]) : bufsize))
+ memset(buf, 0, bufsize);
+ } else {
+ if ((place = map[elem]) < 0) {
+ memset (buf, 0, bufsize);
+ ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Invalid element (%d) requested.\n", elem);
+ } else {
+ if (elem < MISDN_CFG_LAST) {
+ switch (port_spec[place].type) {
+ case MISDN_CTYPE_STR:
+ if (port_cfg[port][place].str) {
+ if (!memccpy(buf, port_cfg[port][place].str, 0, bufsize))
+ memset(buf, 0, 1);
+ } else if (port_cfg[0][place].str) {
+ if (!memccpy(buf, port_cfg[0][place].str, 0, bufsize))
+ memset(buf, 0, 1);
+ }
+ break;
+ default:
+ if (port_cfg[port][place].any)
+ memcpy(buf, port_cfg[port][place].any, bufsize);
+ else if (port_cfg[0][place].any)
+ memcpy(buf, port_cfg[0][place].any, bufsize);
+ else
+ memset(buf, 0, bufsize);
+ }
+ } else {
+ switch (gen_spec[place].type) {
+ case MISDN_CTYPE_STR:
+ if (!general_cfg[place].str || !memccpy(buf, general_cfg[place].str, 0, bufsize))
+ memset(buf, 0, 1);
+ break;
+ default:
+ if (general_cfg[place].any)
+ memcpy(buf, general_cfg[place].any, bufsize);
+ else
+ memset(buf, 0, bufsize);
+ }
+ }
+ }
+ }
+ misdn_cfg_unlock();
+}
+
+int misdn_cfg_is_msn_valid (int port, char* msn)
+{
+ int re = 0;
+ struct msn_list *iter;
+
+ if (!misdn_cfg_is_port_valid(port)) {
+ ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
+ return 0;
+ }
+
+ misdn_cfg_lock();
+ if (port_cfg[port][map[MISDN_CFG_MSNS]].ml)
+ iter = port_cfg[port][map[MISDN_CFG_MSNS]].ml;
+ else
+ iter = port_cfg[0][map[MISDN_CFG_MSNS]].ml;
+ for (; iter; iter = iter->next)
+ if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) {
+ re = 1;
+ break;
+ }
+ misdn_cfg_unlock();
+
+ return re;
+}
+
+int misdn_cfg_is_port_valid (int port)
+{
+ return (port >= 1 && port <= max_ports);
+}
+
+int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth)
+{
+ int i, re = 0;
+ char *method = NULL;
+
+ misdn_cfg_lock();
+ for (i = 1; i <= max_ports; i++) {
+ if (port_cfg[i] && port_cfg[i][map[MISDN_CFG_GROUPNAME]].str) {
+ if (!strcasecmp(port_cfg[i][map[MISDN_CFG_GROUPNAME]].str, group))
+ method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ?
+ port_cfg[i][map[MISDN_CFG_METHOD]].str : port_cfg[0][map[MISDN_CFG_METHOD]].str);
+ }
+ }
+ if (method) {
+ switch (meth) {
+ case METHOD_STANDARD: re = !strcasecmp(method, "standard");
+ break;
+ case METHOD_ROUND_ROBIN: re = !strcasecmp(method, "round_robin");
+ break;
+ }
+ }
+ misdn_cfg_unlock();
+
+ return re;
+}
+
+void misdn_cfg_get_ports_string (char *ports)
+{
+ char tmp[16];
+ int l, i;
+ int gn = map[MISDN_CFG_GROUPNAME];
+
+ *ports = 0;
+
+ misdn_cfg_lock();
+ for (i = 1; i <= max_ports; i++) {
+ if (port_cfg[i][gn].str) {
+ if (ptp[i])
+ sprintf(tmp, "%dptp,", i);
+ else
+ sprintf(tmp, "%d,", i);
+ strcat(ports, tmp);
+ }
+ }
+ misdn_cfg_unlock();
+
+ if ((l = strlen(ports)))
+ ports[l-1] = 0;
+}
+
+void misdn_cfg_get_config_string (int port, enum misdn_cfg_elements elem, char* buf, int bufsize)
+{
+ int place;
+ char tempbuf[BUFFERSIZE] = "";
+ struct msn_list *iter;
+
+ if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
+ *buf = 0;
+ ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
+ return;
+ }
+
+ place = map[elem];
+
+ misdn_cfg_lock();
+ if (elem == MISDN_CFG_PTP) {
+ snprintf(buf, bufsize, " -> ptp: %s", ptp[port] ? "yes" : "no");
+ }
+ else if (elem > MISDN_CFG_FIRST && elem < MISDN_CFG_LAST) {
+ switch (port_spec[place].type) {
+ case MISDN_CTYPE_INT:
+ case MISDN_CTYPE_BOOLINT:
+ if (port_cfg[port][place].num)
+ snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[port][place].num);
+ else if (port_cfg[0][place].num)
+ snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[0][place].num);
+ else
+ snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+ break;
+ case MISDN_CTYPE_BOOL:
+ if (port_cfg[port][place].num)
+ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[port][place].num ? "yes" : "no");
+ else if (port_cfg[0][place].num)
+ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[0][place].num ? "yes" : "no");
+ else
+ snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+ break;
+ case MISDN_CTYPE_ASTGROUP:
+ if (port_cfg[port][place].grp)
+ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
+ ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp));
+ else if (port_cfg[0][place].grp)
+ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
+ ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp));
+ else
+ snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+ break;
+ case MISDN_CTYPE_MSNLIST:
+ if (port_cfg[port][place].ml)
+ iter = port_cfg[port][place].ml;
+ else
+ iter = port_cfg[0][place].ml;
+ if (iter) {
+ for (; iter; iter = iter->next)
+ sprintf(tempbuf, "%s%s, ", tempbuf, iter->msn);
+ tempbuf[strlen(tempbuf)-2] = 0;
+ }
+ snprintf(buf, bufsize, " -> msns: %s", *tempbuf ? tempbuf : "none");
+ break;
+ case MISDN_CTYPE_STR:
+ if ( port_cfg[port][place].str) {
+ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[port][place].str);
+ } else if (port_cfg[0][place].str) {
+ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[0][place].str);
+ } else {
+ snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+ }
+ break;
+ }
+ } else if (elem > MISDN_GEN_FIRST && elem < MISDN_GEN_LAST) {
+ switch (gen_spec[place].type) {
+ case MISDN_CTYPE_INT:
+ case MISDN_CTYPE_BOOLINT:
+ if (general_cfg[place].num)
+ snprintf(buf, bufsize, " -> %s: %d", gen_spec[place].name, *general_cfg[place].num);
+ else
+ snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
+ break;
+ case MISDN_CTYPE_BOOL:
+ if (general_cfg[place].num)
+ snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, *general_cfg[place].num ? "yes" : "no");
+ else
+ snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
+ break;
+ case MISDN_CTYPE_STR:
+ if ( general_cfg[place].str) {
+ snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, general_cfg[place].str);
+ } else {
+ snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
+ }
+ break;
+ default:
+ snprintf(buf, bufsize, " -> type of %s not handled yet", gen_spec[place].name);
+ break;
+ }
+ } else {
+ *buf = 0;
+ ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Invalid config element (%d) requested.\n", elem);
+ }
+ misdn_cfg_unlock();
+}
+
+int misdn_cfg_get_next_port (int port)
+{
+ int p = -1;
+ int gn = map[MISDN_CFG_GROUPNAME];
+
+ misdn_cfg_lock();
+ for (port++; port <= max_ports; port++) {
+ if (port_cfg[port][gn].str) {
+ p = port;
+ break;
+ }
+ }
+ misdn_cfg_unlock();
+
+ return p;
+}
+
+int misdn_cfg_get_next_port_spin (int port)
+{
+ int p = misdn_cfg_get_next_port(port);
+ return (p > 0) ? p : misdn_cfg_get_next_port(0);
+}
+
+static int _parse (union misdn_cfg_pt *dest, char *value, enum misdn_cfg_type type, int boolint_def)
+{
+ int re = 0;
+ int len, tmp;
+ char *valtmp;
+
+ switch (type) {
+ case MISDN_CTYPE_STR:
+ if ((len = strlen(value))) {
+ dest->str = (char *)malloc((len + 1) * sizeof(char));
+ strncpy(dest->str, value, len);
+ dest->str[len] = 0;
+ } else {
+ dest->str = (char *)malloc( sizeof(char));
+ dest->str[0] = 0;
+ }
+ break;
+ case MISDN_CTYPE_INT:
+ {
+ char *pat;
+ if (strchr(value,'x'))
+ pat="%x";
+ else
+ pat="%d";
+ if (sscanf(value, pat, &tmp)) {
+ dest->num = (int *)malloc(sizeof(int));
+ memcpy(dest->num, &tmp, sizeof(int));
+ } else
+ re = -1;
+ }
+ break;
+ case MISDN_CTYPE_BOOL:
+ dest->num = (int *)malloc(sizeof(int));
+ *(dest->num) = (ast_true(value) ? 1 : 0);
+ break;
+ case MISDN_CTYPE_BOOLINT:
+ dest->num = (int *)malloc(sizeof(int));
+ if (sscanf(value, "%d", &tmp)) {
+ memcpy(dest->num, &tmp, sizeof(int));
+ } else {
+ *(dest->num) = (ast_true(value) ? boolint_def : 0);
+ }
+ break;
+ case MISDN_CTYPE_MSNLIST:
+ for (valtmp = strsep(&value, ","); valtmp; valtmp = strsep(&value, ",")) {
+ if ((len = strlen(valtmp))) {
+ struct msn_list *ml = (struct msn_list *)malloc(sizeof(struct msn_list));
+ ml->msn = (char *)calloc(len+1, sizeof(char));
+ strncpy(ml->msn, valtmp, len);
+ ml->next = dest->ml;
+ dest->ml = ml;
+ }
+ }
+ break;
+ case MISDN_CTYPE_ASTGROUP:
+ dest->grp = (ast_group_t *)malloc(sizeof(ast_group_t));
+ *(dest->grp) = ast_get_group(value);
+ break;
+ }
+
+ return re;
+}
+
+static void _build_general_config (struct ast_variable *v)
+{
+ int pos;
+
+ for (; v; v = v->next) {
+ if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) ||
+ (_parse(&general_cfg[pos], v->value, gen_spec[pos].type, gen_spec[pos].boolint_def) < 0))
+ CLI_ERROR(v->name, v->value, "general");
+ }
+}
+
+static void _build_port_config (struct ast_variable *v, char *cat)
+{
+ int pos, i;
+ union misdn_cfg_pt cfg_tmp[NUM_PORT_ELEMENTS];
+ int cfg_for_ports[max_ports + 1];
+
+ if (!v || !cat)
+ return;
+
+ memset(cfg_tmp, 0, sizeof(cfg_tmp));
+ memset(cfg_for_ports, 0, sizeof(cfg_for_ports));
+
+ if (!strcasecmp(cat, "default")) {
+ cfg_for_ports[0] = 1;
+ }
+
+ if (((pos = get_cfg_position("name", PORT_CFG)) < 0) ||
+ (_parse(&cfg_tmp[pos], cat, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) {
+ CLI_ERROR(v->name, v->value, cat);
+ return;
+ }
+
+ for (; v; v = v->next) {
+ if (!strcasecmp(v->name, "ports")) {
+ char *token;
+ char ptpbuf[BUFFERSIZE] = "";
+ int start, end;
+ for (token = strsep(&v->value, ","); token; token = strsep(&v->value, ","), *ptpbuf = 0) {
+ if (!*token)
+ continue;
+ if (sscanf(token, "%d-%d%s", &start, &end, ptpbuf) >= 2) {
+ for (; start <= end; start++) {
+ if (start <= max_ports && start > 0) {
+ cfg_for_ports[start] = 1;
+ ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
+ } else
+ CLI_ERROR(v->name, v->value, cat);
+ }
+ } else {
+ if (sscanf(token, "%d%s", &start, ptpbuf)) {
+ if (start <= max_ports && start > 0) {
+ cfg_for_ports[start] = 1;
+ ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
+ } else
+ CLI_ERROR(v->name, v->value, cat);
+ } else
+ CLI_ERROR(v->name, v->value, cat);
+ }
+ }
+ } else {
+ if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) ||
+ (_parse(&cfg_tmp[pos], v->value, port_spec[pos].type, port_spec[pos].boolint_def) < 0))
+ CLI_ERROR(v->name, v->value, cat);
+ }
+ }
+
+ for (i = 0; i < (max_ports + 1); ++i) {
+ if (cfg_for_ports[i]) {
+ memcpy(port_cfg[i], cfg_tmp, sizeof(cfg_tmp));
+ }
+ }
+}
+
+void misdn_cfg_update_ptp (void)
+{
+ char misdn_init[BUFFERSIZE];
+ char line[BUFFERSIZE];
+ FILE *fp;
+ char *tok, *p, *end;
+ int port;
+
+ misdn_cfg_get(0, MISDN_GEN_MISDN_INIT, &misdn_init, sizeof(misdn_init));
+
+ if (misdn_init) {
+ fp = fopen(misdn_init, "r");
+ if (fp) {
+ while(fgets(line, sizeof(line), fp)) {
+ if (!strncmp(line, "nt_ptp", 6)) {
+ for (tok = strtok_r(line,",=", &p);
+ tok;
+ tok = strtok_r(NULL,",=", &p)) {
+ port = strtol(tok, &end, 10);
+ if (end != tok && misdn_cfg_is_port_valid(port)) {
+ misdn_cfg_lock();
+ ptp[port] = 1;
+ misdn_cfg_unlock();
+ }
+ }
+ }
+ }
+ fclose(fp);
+ } else {
+ ast_log(LOG_WARNING,"Couldn't open %s: %s\n", misdn_init, strerror(errno));
+ }
+ }
+}
+
+static void _fill_defaults (void)
+{
+ int i;
+
+ for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
+ if (!port_cfg[0][i].any && strcasecmp(port_spec[i].def, NO_DEFAULT))
+ _parse(&(port_cfg[0][i]), (char *)port_spec[i].def, port_spec[i].type, port_spec[i].boolint_def);
+ }
+ for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
+ if (!general_cfg[i].any && strcasecmp(gen_spec[i].def, NO_DEFAULT))
+ _parse(&(general_cfg[i]), (char *)gen_spec[i].def, gen_spec[i].type, gen_spec[i].boolint_def);
+ }
+}
+
+void misdn_cfg_reload (void)
+{
+ misdn_cfg_init (0);
+}
+
+void misdn_cfg_destroy (void)
+{
+ misdn_cfg_lock();
+
+ _free_port_cfg();
+ _free_general_cfg();
+
+ free(port_cfg);
+ free(general_cfg);
+ free(ptp);
+ free(map);
+
+ misdn_cfg_unlock();
+ ast_mutex_destroy(&config_mutex);
+}
+
+void misdn_cfg_init (int this_max_ports)
+{
+ char config[] = "misdn.conf";
+ char *cat, *p;
+ int i;
+ struct ast_config *cfg;
+ struct ast_variable *v;
+
+ if (!(cfg = AST_LOAD_CFG(config))) {
+ ast_log(LOG_WARNING,"no misdn.conf ?\n");
+ return;
+ }
+
+ misdn_cfg_lock();
+
+ if (this_max_ports) {
+ /* this is the first run */
+ max_ports = this_max_ports;
+ p = (char *)calloc(1, (max_ports + 1) * sizeof(union misdn_cfg_pt *)
+ + (max_ports + 1) * NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt));
+ port_cfg = (union misdn_cfg_pt **)p;
+ p += (max_ports + 1) * sizeof(union misdn_cfg_pt *);
+ for (i = 0; i <= max_ports; ++i) {
+ port_cfg[i] = (union misdn_cfg_pt *)p;
+ p += NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt);
+ }
+ general_cfg = (union misdn_cfg_pt *)calloc(1, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
+ ptp = (int *)calloc(max_ports + 1, sizeof(int));
+ map = (int *)calloc(MISDN_GEN_LAST + 1, sizeof(int));
+ _enum_array_map();
+ }
+ else {
+ /* misdn reload */
+ _free_port_cfg();
+ _free_general_cfg();
+ memset(port_cfg[0], 0, NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt) * (max_ports + 1));
+ memset(general_cfg, 0, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
+ memset(ptp, 0, sizeof(int) * (max_ports + 1));
+ }
+
+ cat = ast_category_browse(cfg, NULL);
+
+ while(cat) {
+ v = ast_variable_browse(cfg, cat);
+ if (!strcasecmp(cat,"general")) {
+ _build_general_config(v);
+ } else {
+ _build_port_config(v, cat);
+ }
+ cat = ast_category_browse(cfg,cat);
+ }
+
+ _fill_defaults();
+
+ misdn_cfg_unlock();
+ AST_DESTROY_CFG(cfg);
+}