summaryrefslogtreecommitdiff
path: root/channels/chan_dahdi.c
diff options
context:
space:
mode:
authorKevin P. Fleming <kpfleming@digium.com>2009-04-30 21:42:35 +0000
committerKevin P. Fleming <kpfleming@digium.com>2009-04-30 21:42:35 +0000
commitd9d2779008f198c75b7994afe0c472b653bae347 (patch)
treedb4dfab0d00b9a45bd0d4de6e74ed32e37347e47 /channels/chan_dahdi.c
parent91dde03ba8c34172c9671f50bbbcaa5a9a211e28 (diff)
Add buffer and echo canceller control to CHANNEL() dialplan function for DAHDI channels
Adds ability for CHANNEL() dialplan function, when used on DAHDI channels, to temporarily change the number of buffers and/or the buffer policy, and also to enable, disable, or switch the echo canceller between FAX/data and voice modes. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@191411 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_dahdi.c')
-rw-r--r--channels/chan_dahdi.c180
1 files changed, 129 insertions, 51 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index ab6386a24..d2f18a97a 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -782,10 +782,10 @@ static struct dahdi_pvt {
unsigned int echocanon:1;
/*! \brief TRUE if a fax tone has already been handled. */
unsigned int faxhandled:1;
- /*! \brief TRUE if dynamic faxbuffers are configured for use, default is OFF */
+ /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
unsigned int usefaxbuffers:1;
- /*! \brief TRUE while dynamic faxbuffers are in use */
- unsigned int faxbuffersinuse:1;
+ /*! TRUE while buffer configuration override is in use */
+ unsigned int bufferoverrideinuse:1;
/*! \brief TRUE if over a radio and dahdi_read() has been called. */
unsigned int firstradio:1;
/*!
@@ -1381,8 +1381,6 @@ static struct dahdi_chan_conf dahdi_chan_conf_default(void)
.buf_policy = DAHDI_POLICY_IMMEDIATE,
.buf_no = numbufs,
.usefaxbuffers = 0,
- .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
- .faxbuf_no = numbufs,
},
.timing = {
.prewinktime = -1,
@@ -1417,6 +1415,7 @@ static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
static int handle_init_event(struct dahdi_pvt *i, int event);
+static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
static const struct ast_channel_tech dahdi_tech = {
.type = "DAHDI",
@@ -1437,6 +1436,7 @@ static const struct ast_channel_tech dahdi_tech = {
.fixup = dahdi_fixup,
.setoption = dahdi_setoption,
.func_channel_read = dahdi_func_read,
+ .func_channel_write = dahdi_func_write,
};
#ifdef HAVE_PRI
@@ -3982,8 +3982,7 @@ static void destroy_all_channels(void)
/* Free associated memory */
if (pl)
destroy_dahdi_pvt(&pl);
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
+ ast_verb(3, "Unregistered channel %d\n", x);
}
iflist = NULL;
ifcount = 0;
@@ -4515,7 +4514,7 @@ static int dahdi_hangup(struct ast_channel *ast)
p->dsp = NULL;
}
- if (p->faxbuffersinuse) {
+ if (p->bufferoverrideinuse) {
/* faxbuffers are in use, revert them */
struct dahdi_bufferinfo bi = {
.txbufpolicy = p->buf_policy,
@@ -4528,7 +4527,7 @@ static int dahdi_hangup(struct ast_channel *ast)
if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
}
- p->faxbuffersinuse = 0;
+ p->bufferoverrideinuse = 0;
}
law = DAHDI_LAW_DEFAULT;
@@ -5051,7 +5050,8 @@ static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int
static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
{
struct dahdi_pvt *p = chan->tech_pvt;
-
+ int res = 0;
+
if (!strcasecmp(data, "rxgain")) {
ast_mutex_lock(&p->lock);
snprintf(buf, len, "%f", p->rxgain);
@@ -5062,10 +5062,108 @@ static int dahdi_func_read(struct ast_channel *chan, const char *function, char
ast_mutex_unlock(&p->lock);
} else {
ast_copy_string(buf, "", len);
+ res = -1;
}
+
+ return res;
+}
+
+
+static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
+{
+ int res;
+ char policy_str[21] = "";
+
+ if ((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) {
+ ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
+ return 1;
+ }
+ if (*num_buffers < 0) {
+ ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
+ return -1;
+ }
+ if (!strcasecmp(policy_str, "full")) {
+ *policy = DAHDI_POLICY_WHEN_FULL;
+ } else if (!strcasecmp(policy_str, "immediate")) {
+ *policy = DAHDI_POLICY_IMMEDIATE;
+#if defined(HAVE_DAHDI_HALF_FULL)
+ } else if (!strcasecmp(policy_str, "half")) {
+ *policy = DAHDI_POLICY_HALF_FULL;
+#endif
+ } else {
+ ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
+ return -1;
+ }
+
return 0;
}
+static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
+{
+ struct dahdi_pvt *p = chan->tech_pvt;
+ int res = 0;
+
+ if (!strcasecmp(data, "buffers")) {
+ int num_bufs, policy;
+
+ if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
+ struct dahdi_bufferinfo bi = {
+ .txbufpolicy = policy,
+ .rxbufpolicy = policy,
+ .bufsize = p->bufsize,
+ .numbufs = num_bufs,
+ };
+ int bpres;
+
+ if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
+ ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
+ } else {
+ p->bufferoverrideinuse = 1;
+ }
+ } else {
+ res = -1;
+ }
+ } else if (!strcasecmp(data, "echocan_mode")) {
+ if (!strcasecmp(value, "on")) {
+ ast_mutex_lock(&p->lock);
+ dahdi_enable_ec(p);
+ ast_mutex_unlock(&p->lock);
+ } else if (!strcasecmp(value, "off")) {
+ ast_mutex_lock(&p->lock);
+ dahdi_disable_ec(p);
+ ast_mutex_unlock(&p->lock);
+ } else if (!strcasecmp(value, "fax")) {
+ int blah = 1;
+
+ ast_mutex_lock(&p->lock);
+ if (!p->echocanon) {
+ dahdi_enable_ec(p);
+ }
+ if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
+ ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
+ }
+ ast_mutex_unlock(&p->lock);
+ } else if (!strcasecmp(value, "voice")) {
+ int blah = 0;
+
+ ast_mutex_lock(&p->lock);
+ if (!p->echocanon) {
+ dahdi_enable_ec(p);
+ }
+ if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
+ ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
+ }
+ ast_mutex_unlock(&p->lock);
+ } else {
+ ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
+ res = -1;
+ }
+ } else {
+ res = -1;
+ }
+
+ return res;
+}
static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
{
@@ -5661,7 +5759,7 @@ static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_fra
/* Fax tone -- Handle and return NULL */
if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
/* If faxbuffers are configured, use them for the fax transmission */
- if (p->usefaxbuffers && !p->faxbuffersinuse) {
+ if (p->usefaxbuffers && !p->bufferoverrideinuse) {
struct dahdi_bufferinfo bi = {
.txbufpolicy = p->faxbuf_policy,
.bufsize = p->bufsize,
@@ -5672,7 +5770,7 @@ static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_fra
if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
} else {
- p->faxbuffersinuse = 1;
+ p->bufferoverrideinuse = 1;
}
}
p->faxhandled = 1;
@@ -5784,9 +5882,23 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
switch (res) {
case DAHDI_EVENT_EC_DISABLED:
- ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
+ ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
p->echocanon = 0;
break;
+#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
+ case DAHDI_EVENT_TX_CED_DETECTED:
+ ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
+ break;
+ case DAHDI_EVENT_RX_CED_DETECTED:
+ ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
+ break;
+ case DAHDI_EVENT_EC_NLP_DISABLED:
+ ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
+ break;
+ case DAHDI_EVENT_EC_NLP_ENABLED:
+ ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
+ break;
+#endif
case DAHDI_EVENT_BITSCHANGED:
#ifdef HAVE_OPENR2
if (p->sig != SIG_MFCR2) {
@@ -16331,48 +16443,14 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
return -1;
ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
} else if (!strcasecmp(v->name, "buffers")) {
- int res;
- char policy[21] = "";
-
- res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
- if (res != 2) {
- ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
- confp->chan.buf_no = numbufs;
- continue;
- }
- if (confp->chan.buf_no < 0)
+ if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
+ ast_log(LOG_WARNING, "Using default buffer policy.\n");
confp->chan.buf_no = numbufs;
- if (!strcasecmp(policy, "full")) {
- confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
- } else if (!strcasecmp(policy, "immediate")) {
confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
-#ifdef HAVE_DAHDI_HALF_FULL
- } else if (!strcasecmp(policy, "half_full")) {
- confp->chan.buf_policy = DAHDI_POLICY_HALF_FULL;
-#endif
- } else {
- ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
}
} else if (!strcasecmp(v->name, "faxbuffers")) {
- int res;
- char policy[21] = "";
-
- res = sscanf(v->value, "%d,%20s", &confp->chan.faxbuf_no, policy);
- if (res != 2) {
- ast_log(LOG_WARNING, "Parsing faxbuffers option data failed, using defaults.\n");
- confp->chan.faxbuf_no = numbufs;
- continue;
- }
- confp->chan.usefaxbuffers = 1;
- if (confp->chan.faxbuf_no < 0)
- confp->chan.faxbuf_no = numbufs;
- if (!strcasecmp(policy, "full")) {
- confp->chan.faxbuf_policy = DAHDI_POLICY_WHEN_FULL;
- } else if (!strcasecmp(policy, "immediate")) {
- confp->chan.faxbuf_policy = DAHDI_POLICY_IMMEDIATE;
- } else {
- ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
- confp->chan.usefaxbuffers = 0;
+ if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
+ confp->chan.usefaxbuffers = 1;
}
} else if (!strcasecmp(v->name, "dahdichan")) {
ast_copy_string(dahdichan, v->value, sizeof(dahdichan));