[asterisk-ss7] asterisk oh323 - chan-ss7 echo problem
Jacob Tinning
tinning at sifira.dk
Mon May 1 00:08:27 MST 2006
On Fri, 28 Apr 2006, Luciano Ramos wrote:
> I've checked the source code of chan_ss7.c and it doesn't have any calls to
> turn the echo canceller on, is any workaround available in the meantime the
> next release of chan_ss7 is released?
Well.. chan_ss7-0.8.4 is not official yet, but attached to this mail is a
patch. It includes the echo-cancellation + a fix for the T1-timer crash.
The patch require a small modification to your ss7.conf file.
For each [link-XXX] section, add the following three lines:
; echocancel: allways | 31speech | no
echocancel=allways
; echocan_taps: 32 | 64 | 128 | 256
echocan_taps=32
; echocan_train: between 10ms and 1000ms
echocan_train=350
The "echocancel=31speech" should be used if you only want to enable
echo-cancellation on 3.1KHz speech calls.
Mvh. Jacob
--
Jacob Tinning
System Developer SIFIRA A/S
-------------- next part --------------
diff -u chan_ss7-0.8.3/chan_ss7.c chan_ss7-0.8.3d/chan_ss7.c
--- chan_ss7-0.8.3/chan_ss7.c 2006-03-17 10:11:57.000000000 +0100
+++ chan_ss7-0.8.3d/chan_ss7.c 2006-05-01 08:57:56.000000000 +0200
@@ -133,6 +133,8 @@
struct iam iam; /* Last incoming IAM parameters */
char* addr; /* called addr */
int attempts; /* Number of outgoing call attempts on addr */
+ int echocan_start;
+ int echocancel;
unsigned char buffer[AST_FRIENDLY_OFFSET + AUDIO_READSIZE];
struct ast_frame frame;
@@ -213,6 +215,8 @@
static struct ss7_chan* reattempt_call(struct ss7_chan *pvt);
static void *continuity_check_thread_main(void *data);
static void handle_complete_address(struct ss7_chan *pvt);
+static void zt_disable_ec(struct ss7_chan *pvt);
+static int zt_enable_ec(struct ss7_chan *pvt);
static const struct ast_channel_tech ss7_tech = {
.type = type,
@@ -762,7 +766,7 @@
struct ss7_chan *pvt = arg;
ast_log(LOG_NOTICE, "T1 timeout (waiting for RLC) CIC=%d.\n", pvt->cic);
- isup_send_rel(pvt, pvt->owner->hangupcause);
+ isup_send_rel(pvt, pvt->hangupcause);
return 1; /* Run us again the next period */
}
@@ -1594,6 +1598,7 @@
isup_msg_start_optional_part(msg, sizeof(msg), &varptr, ¤t);
/* Calling partys number Q.763 (3.10). */
+ ast_log(LOG_NOTICE, "cid_pres=0x%X\n", chan->cid.cid_pres);
if((chan->cid.cid_pres & AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED) {
pres_restr = 1;
} else {
@@ -1688,6 +1693,8 @@
initiate_release_circuit(pvt, chan->hangupcause);
}
+ zt_disable_ec(pvt);
+
ast_mutex_unlock(&pvt->lock);
ast_mutex_unlock(&glock);
@@ -1730,6 +1737,12 @@
}
pvt->state = ST_CONNECTED;
+ /* Start echo-cancelling if required */
+ if (pvt->echocan_start) {
+ zt_enable_ec(pvt);
+ pvt->echocan_start = 0;
+ }
+
ast_mutex_unlock(&pvt->lock);
return 0;
@@ -2245,6 +2258,51 @@
return newpvt;
}
+static int zt_enable_ec(struct ss7_chan *pvt) {
+ int res;
+ int x, y;
+ int z = 1;
+
+ res = ioctl(pvt->zaptel_fd, ZT_AUDIOMODE, &z);
+ if (res)
+ ast_log(LOG_WARNING, "Unable to set fd %d to audiomode\n", pvt->zaptel_fd);
+
+ x = pvt->link->echocan_taps;
+ res = ioctl(pvt->zaptel_fd, ZT_ECHOCANCEL, &x);
+ if (res) {
+ ast_log(LOG_WARNING, "Unable to enable echo cancellation on cic %d\n", pvt->cic);
+ return res;
+ } else {
+ pvt->echocancel = 1;
+ ast_log(LOG_DEBUG, "Enabled echo cancellation on cic %d\n", pvt->cic);
+ y = pvt->link->echocan_train;
+ res = ioctl(pvt->zaptel_fd, ZT_ECHOTRAIN, &y);
+ if (res) {
+ ast_log(LOG_WARNING, "Unable to request echo training on cic %d\n", pvt->cic);
+ return res;
+ } else {
+ ast_log(LOG_DEBUG, "Engaged echo training on cic %d\n", pvt->cic);
+ }
+ }
+ return 0;
+}
+
+
+static void zt_disable_ec(struct ss7_chan *pvt) {
+ int res;
+ int x = 0;
+
+ if (pvt->echocancel) {
+ res = ioctl(pvt->zaptel_fd, ZT_ECHOCANCEL, &x);
+ if (res)
+ ast_log(LOG_WARNING, "Unable to disable echo cancellation on cic %d\n", pvt->cic);
+ else
+ ast_log(LOG_DEBUG, "disabled echo cancellation on cic %d\n", pvt->cic);
+ }
+ pvt->echocancel = 0;
+}
+
+
static int resolve_dual_seizure(struct ss7_chan *pvt, struct isup_msg *inmsg) {
/* Q.764 2.9.1.4: The switch with the higher point code controls even numbered CICs */
int iscontrolling = (inmsg->dpc > inmsg->opc) && ((inmsg->cic & 1) == 0);
@@ -2261,14 +2319,14 @@
{
struct ast_channel* chan = pvt->owner;
- ast_log(LOG_NOTICE, "IAM (cic=%d): ANI=%s DNI=%s RNI=%s redirect=%s/%d complete=%d.\n",
+ ast_log(LOG_NOTICE, "IAM (cic=%d): ANI=%s DNI=%s RNI=%s redirect=%s/%d complete=%d. echocontr=%d\n",
pvt->cic,
inmsg->iam.ani.restricted ? "*****" : inmsg->iam.ani.num,
inmsg->iam.dni.num,
inmsg->iam.rni.restricted ? "*****" : inmsg->iam.rni.num,
inmsg->iam.redir_inf.is_redirect ? "yes" : "no",
inmsg->iam.redir_inf.reason,
- inmsg->iam.dni.complete);
+ inmsg->iam.dni.complete, inmsg->iam.echocontrol);
if(pvt->state != ST_IDLE) {
if (resolve_dual_seizure(pvt, inmsg)) {
ast_log(LOG_WARNING, "Dual seizure/invalid IAM, discarding on CIC=%d.\n",
@@ -2294,6 +2352,16 @@
}
}
+ switch (pvt->link->echocancel) {
+ case EC_ALLWAYS:
+ pvt->echocan_start = 1;
+ break;
+
+ case EC_31SPEECH:
+ pvt->echocan_start = (inmsg->iam.echocontrol == 0 && inmsg->iam.trans_medium == 0x3);
+ break;
+ }
+
remove_from_idlelist(pvt);
pvt->state = ST_GOT_IAM;
memcpy(&pvt->iam, &inmsg->iam, sizeof(pvt->iam));
@@ -2326,7 +2394,6 @@
/* Q.764 (2.1.4.6 a): When receiving ACM, stop T7 and start T9. */
t7_clear(pvt);
- t9_start(chan);
if(pvt->state != ST_SENT_IAM) {
ast_log(LOG_NOTICE, "Got ACM message, but sent no IAM, on CIC=%d?!?",
@@ -2336,6 +2403,7 @@
reset_circuit(pvt);
return;
}
+ t9_start(chan);
if(chan == NULL) {
ast_log(LOG_NOTICE, "Missing chan pointer for CIC=%d, processing ACM?!?\n", pvt->cic);
@@ -2372,6 +2440,9 @@
return;
}
+ /* Start echo-cancelling */
+ zt_enable_ec(pvt);
+
ast_queue_frame(chan, &answer_frame);
pvt->state = ST_CONNECTED;
check_obci(pvt, inmsg->anm.obc_ind);
@@ -3681,6 +3752,14 @@
return RESULT_SUCCESS;
}
+static int cmd_version(int fd, int argc, char *argv[]) {
+
+ ast_cli(fd, "chan_ss7, v.0.8.3d\n");
+
+ return RESULT_SUCCESS;
+}
+
+
static int cmd_dump_status(int fd, int argc, char *argv[]) {
ast_mutex_lock(&dump_mutex);
@@ -3705,6 +3784,7 @@
return RESULT_SUCCESS;
}
+
static char *complete_generic(char *word, int state, char **options, int entries) {
int which = 0;
int i;
@@ -4071,6 +4151,12 @@
complete_dump_stop
},
+ { {"ss7", "version", NULL}, cmd_version,
+ "Show current version of chan_ss7",
+ "Usage: ss7 version\n",
+ NULL
+ },
+
{ {"ss7", "dump", "status", NULL}, cmd_dump_status,
"Stop what dumps are running",
"Usage: ss7 dump status\n",
@@ -4211,6 +4297,8 @@
pvt->sending_dtmf = 0;
pvt->dsp = NULL;
pvt->hangupcause = 0;
+ pvt->echocan_start = 0;
+ pvt->echocancel = 0;
pvt->has_inband_ind = 0;
pvt->grs_count = -1;
pvt->cgb_mask = 0;
Only in chan_ss7-0.8.3d: chan_ss7.o
Only in chan_ss7-0.8.3d: chan_ss7.so
Only in chan_ss7-0.8.3d: cluster.o
diff -u chan_ss7-0.8.3/config.c chan_ss7-0.8.3d/config.c
--- chan_ss7-0.8.3/config.c 2006-03-16 11:59:37.000000000 +0100
+++ chan_ss7-0.8.3d/config.c 2006-05-01 08:57:56.000000000 +0200
@@ -353,6 +353,11 @@
return -1;
}
+ /* Echo cancelation default values */
+ link->echocancel = EC_DISABLED;
+ link->echocan_taps = 128; /* echo cancelation taps, 128 default */
+ link->echocan_train = 300; /* echo cancelation training, 300ms default */
+
v = ast_variable_browse(cfg, cat);
while(v != NULL) {
if(0 == strcasecmp(v->name, "linkset")) {
@@ -411,6 +416,37 @@
}
}
has_schannel = 1;
+
+ } else if(0 == strcasecmp(v->name, "echocancel")) {
+ if (strcasecmp(v->value, "no") == 0) {
+ link->echocancel = EC_DISABLED;
+ } else if (strcasecmp(v->value, "31speech") == 0) {
+ link->echocancel = EC_31SPEECH;
+ } else if (strcasecmp(v->value, "allways") == 0) {
+ link->echocancel = EC_ALLWAYS;
+ } else {
+ ast_log(LOG_ERROR, "Invalid value '%s' for echocancel entry for link '%s'.\n", v->value, link_name);
+ return -1;
+ }
+ } else if(0 == strcasecmp(v->name, "echocan_train")) {
+ if(sscanf(v->value, "%d", &link->echocan_train) != 1 ||
+ link->echocan_train < 10 || link->echocan_train > 1000)
+ {
+ ast_log(LOG_ERROR, "Invalid value '%s' for echocan_train entry for "
+ "link '%s'. should be between 10 and 1000\n",
+ v->value, link_name);
+ return -1;
+ }
+ } else if(0 == strcasecmp(v->name, "echocan_taps")) {
+ if(!(sscanf(v->value, "%d", &link->echocan_taps) == 1 &&
+ (link->echocan_taps == 32 || link->echocan_taps == 64 ||
+ link->echocan_taps == 128 || link->echocan_taps == 256)))
+ {
+ ast_log(LOG_ERROR, "Invalid value '%s' for echocan_taps entry for "
+ "link '%s'. should be 32, 64, 128 or 256\n",
+ v->value, link_name);
+ return -1;
+ }
} else {
ast_log(LOG_ERROR, "Unknown config option '%s', aborting.\n", v->name);
return -1;
diff -u chan_ss7-0.8.3/config.h chan_ss7-0.8.3d/config.h
--- chan_ss7-0.8.3/config.h 2006-03-16 11:52:59.000000000 +0100
+++ chan_ss7-0.8.3d/config.h 2006-05-01 08:57:56.000000000 +0200
@@ -39,6 +39,10 @@
#define RECEIVERPORT 4321
+
+/* Echo cancelation taps */
+enum {EC_DISABLED, EC_ALLWAYS, EC_31SPEECH};
+
typedef enum {STATE_UNKNOWN, STATE_ALIVE, STATE_DEAD} alivestate;
struct linkset {
char* name;
@@ -74,6 +78,9 @@
int enabled;
int send_sltm;
int linkix;
+ int echocancel;
+ int echocan_taps;
+ int echocan_train;
struct linkset* linkset;
struct host* on_host;
struct receiver* receiver;
Only in chan_ss7-0.8.3d: config.o
diff -u chan_ss7-0.8.3/isup.c chan_ss7-0.8.3d/isup.c
--- chan_ss7-0.8.3/isup.c 2006-03-16 16:48:01.000000000 +0100
+++ chan_ss7-0.8.3d/isup.c 2006-05-01 08:58:26.000000000 +0200
@@ -308,14 +308,27 @@
/* Decode parameter 0x6 "nature of connection indicators" (Q.763 (3.35)).
For now, only decodes the "continuity check required" part. */
static int decode_noci_contcheck(unsigned char *p, int len, void *data) {
- int *contcheck_ptr = data;
+ struct iam *iam = data;
if(len < 1) {
ast_log(LOG_NOTICE, "Short parameter 'nature of connection indicators', "
"len %d < 1.\n", len);
return 0;
}
- *contcheck_ptr = ((p[0] >> 2) & 0x3) == 0x1;
+ iam->contcheck = ((p[0] >> 2) & 0x3) == 0x1;
+ iam->echocontrol = (p[0] >> 4) & 0x1;
+ return 1;
+}
+
+static int decode_transmission_medium(unsigned char *p, int len, void *data) {
+ struct iam *iam = data;
+
+ if(len < 1) {
+ ast_log(LOG_NOTICE, "Short parameter 'Transmission medium requirement', "
+ "len %d < 1.\n", len);
+ return 0;
+ }
+ iam->trans_medium = p[0];
return 1;
}
@@ -481,6 +494,7 @@
num_dig++;
n->num[i++] = '0';
break;
+
default:
ast_log(LOG_NOTICE, "unknown nature of address indicator 0x%0x.\n",
nature_of_adr_ind);
@@ -552,10 +566,10 @@
msg->iam.redir_inf.is_redirect = 0;
msg->iam.redir_inf.reason = 0;
return param_decode(buf, len,
- IP_NATURE_OF_CONNECTION_INDICATORS, 1, decode_noci_contcheck, &msg->iam.contcheck,
+ IP_NATURE_OF_CONNECTION_INDICATORS, 1, decode_noci_contcheck, &msg->iam,
IP_FORWARD_CALL_INDICATORS, 2, NULL, NULL,
IP_CALLING_PARTYS_CATEGORY, 1, NULL, NULL,
- IP_TRANSMISSION_MEDIUM_REQUIREMENT, 1, NULL, NULL,
+ IP_TRANSMISSION_MEDIUM_REQUIREMENT, 1, decode_transmission_medium, &msg->iam,
0,
IP_CALLED_PARTY_NUMBER, decode_dni, &msg->iam.dni,
0,
diff -u chan_ss7-0.8.3/isup.h chan_ss7-0.8.3d/isup.h
--- chan_ss7-0.8.3/isup.h 2006-03-16 16:47:50.000000000 +0100
+++ chan_ss7-0.8.3d/isup.h 2006-05-01 08:57:56.000000000 +0200
@@ -71,6 +71,7 @@
IP_EVENT_INFORMATION = 0x24, /* (3.21) */
IP_OPTIONAL_BACKWARD_CALL_INDICATORS = 0x29, /* (3.5) */
IP_SUSPEND_RESUME_INDICATORS = 0x22, /* (3.21) */
+ IP_ECHO_CONTROL_INFORMATION = 0x37, /* (3.19) */
};
#define PHONENUM_MAX 20
@@ -122,6 +123,8 @@
struct isup_phonenum rni;
struct isup_redir_info redir_inf;
int contcheck;
+ int echocontrol;
+ unsigned char trans_medium;
} iam;
struct {
struct isup_phonenum sni;
Only in chan_ss7-0.8.3d: isup.o
Only in chan_ss7-0.8.3d: lffifo.o
Only in chan_ss7-0.8.3d: moduletest.o
Only in chan_ss7-0.8.3d: mtp.o
More information about the asterisk-ss7
mailing list