summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_dahdi.c122
-rw-r--r--channels/chan_sip.c97
2 files changed, 156 insertions, 63 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 3567aa9e9..bd11e51ea 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -1507,6 +1507,7 @@ static struct ast_frame *dahdi_exception(struct ast_channel *ast);
static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
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_queryoption(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);
@@ -1529,6 +1530,7 @@ static const struct ast_channel_tech dahdi_tech = {
.indicate = dahdi_indicate,
.fixup = dahdi_fixup,
.setoption = dahdi_setoption,
+ .queryoption = dahdi_queryoption,
.func_channel_read = dahdi_func_read,
.func_channel_write = dahdi_func_write,
};
@@ -5890,6 +5892,66 @@ static int dahdi_answer(struct ast_channel *ast)
return res;
}
+static void disable_dtmf_detect(struct dahdi_pvt *p)
+{
+ int val = 0;
+
+ p->ignoredtmf = 1;
+
+ ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
+
+ if (!p->hardwaredtmf && p->dsp) {
+ p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
+ ast_dsp_set_features(p->dsp, p->dsp_features);
+ }
+}
+
+static void enable_dtmf_detect(struct dahdi_pvt *p)
+{
+ int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
+
+ if (p->channel == CHAN_PSEUDO)
+ return;
+
+ p->ignoredtmf = 0;
+
+ ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
+
+ if (!p->hardwaredtmf && p->dsp) {
+ p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
+ ast_dsp_set_features(p->dsp, p->dsp_features);
+ }
+}
+
+static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
+{
+ char *cp;
+ struct dahdi_pvt *p = chan->tech_pvt;
+
+ /* all supported options require data */
+ if (!data || (*datalen < 1)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ switch (option) {
+ case AST_OPTION_DIGIT_DETECT:
+ cp = (char *) data;
+ *cp = p->ignoredtmf ? 0 : 1;
+ ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
+ break;
+ case AST_OPTION_FAX_DETECT:
+ cp = (char *) data;
+ *cp = (p->callprogress & CALLPROGRESS_FAX) ? 0 : 1;
+ ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
+ break;
+ }
+
+ errno = 0;
+
+ return 0;
+}
+
static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
{
char *cp;
@@ -6072,6 +6134,29 @@ static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int
dahdi_disable_ec(p);
}
break;
+ case AST_OPTION_DIGIT_DETECT:
+ cp = (char *) data;
+ ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
+ if (*cp) {
+ enable_dtmf_detect(p);
+ } else {
+ disable_dtmf_detect(p);
+ }
+ break;
+ case AST_OPTION_FAX_DETECT:
+ cp = (char *) data;
+ if (p->dsp) {
+ ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
+ if (*cp) {
+ p->callprogress |= CALLPROGRESS_FAX;
+ p->dsp_features |= DSP_FEATURE_FAX_DETECT;
+ } else {
+ p->callprogress &= ~CALLPROGRESS_FAX;
+ p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
+ }
+ ast_dsp_set_features(p->dsp, p->dsp_features);
+ }
+ break;
default:
return -1;
}
@@ -6279,39 +6364,6 @@ static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
}
-static void disable_dtmf_detect(struct dahdi_pvt *p)
-{
- int val;
-
- p->ignoredtmf = 1;
-
- val = 0;
- ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
-
- if (!p->hardwaredtmf && p->dsp) {
- p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
- ast_dsp_set_features(p->dsp, p->dsp_features);
- }
-}
-
-static void enable_dtmf_detect(struct dahdi_pvt *p)
-{
- int val;
-
- if (p->channel == CHAN_PSEUDO)
- return;
-
- p->ignoredtmf = 0;
-
- val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
- ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
-
- if (!p->hardwaredtmf && p->dsp) {
- p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
- ast_dsp_set_features(p->dsp, p->dsp_features);
- }
-}
-
static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
{
struct ast_channel *who;
@@ -6814,6 +6866,10 @@ static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_fra
}
}
p->faxhandled = 1;
+ p->callprogress &= ~CALLPROGRESS_FAX;
+ p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
+ ast_dsp_set_features(p->dsp, p->dsp_features);
+ ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
if (strcmp(ast->exten, "fax")) {
const char *target_context = S_OR(ast->macrocontext, ast->context);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 4158ba5d4..4fd774b94 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1833,7 +1833,7 @@ struct sip_pvt {
int laststate; /*!< SUBSCRIBE: Last known extension state */
int dialogver; /*!< SUBSCRIBE: Version for subscription dialog-info */
- struct ast_dsp *vad; /*!< Inband DTMF Detection dsp */
+ struct ast_dsp *dsp; /*!< Inband DTMF Detection dsp */
struct sip_peer *relatedpeer; /*!< If this dialog is related to a peer, which one
Used in peerpoke, mwi subscriptions */
@@ -4076,21 +4076,62 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp
return res;
}
+static void enable_digit_detect(struct sip_pvt *p)
+{
+ if (p->dsp) {
+ return;
+ }
+
+ if (!(p->dsp = ast_dsp_new())) {
+ return;
+ }
+
+ ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT);
+ if (global_relaxdtmf) {
+ ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
+ }
+}
+
+static void disable_digit_detect(struct sip_pvt *p)
+{
+ if (p->dsp) {
+ ast_dsp_free(p->dsp);
+ p->dsp = NULL;
+ }
+}
+
/*! \brief Set an option on a SIP dialog */
static int sip_setoption(struct ast_channel *chan, int option, void *data, int datalen)
{
int res = -1;
struct sip_pvt *p = chan->tech_pvt;
- if (option == AST_OPTION_FORMAT_READ) {
- int format = *(int *)data;
- res = ast_rtp_instance_set_read_format(p->rtp, format);
- } else if (option == AST_OPTION_FORMAT_WRITE) {
- int format = *(int *)data;
- res = ast_rtp_instance_set_write_format(p->rtp, format);
- } else if (option == AST_OPTION_MAKE_COMPATIBLE) {
- struct ast_channel *peer = data;
- res = ast_rtp_instance_make_compatible(chan, p->rtp, peer);
+ switch (option) {
+ case AST_OPTION_FORMAT_READ:
+ res = ast_rtp_instance_set_read_format(p->rtp, *(int *) data);
+ break;
+ case AST_OPTION_FORMAT_WRITE:
+ res = ast_rtp_instance_set_write_format(p->rtp, *(int *) data);
+ break;
+ case AST_OPTION_MAKE_COMPATIBLE:
+ res = ast_rtp_instance_make_compatible(chan, p->rtp, (struct ast_channel *) data);
+ break;
+ case AST_OPTION_DIGIT_DETECT:
+ if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
+ (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
+ char *cp = (char *) data;
+
+ ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
+ if (*cp) {
+ enable_digit_detect(p);
+ } else {
+ disable_digit_detect(p);
+ }
+ res = 0;
+ }
+ break;
+ default:
+ break;
}
return res;
@@ -4102,6 +4143,7 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int
int res = -1;
enum ast_t38_state state = T38_STATE_UNAVAILABLE;
struct sip_pvt *p = (struct sip_pvt *) chan->tech_pvt;
+ char *cp;
switch (option) {
case AST_OPTION_T38_STATE:
@@ -4135,6 +4177,11 @@ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int
res = 0;
break;
+ case AST_OPTION_DIGIT_DETECT:
+ cp = (char *) data;
+ *cp = p->dsp ? 1 : 0;
+ ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
+ break;
default:
break;
}
@@ -5823,7 +5870,6 @@ static const char *hangup_cause2sip(int cause)
return 0;
}
-
/*! \brief sip_hangup: Hangup SIP call
* Part of PBX interface, called from ast_hangup */
static int sip_hangup(struct ast_channel *ast)
@@ -5902,8 +5948,7 @@ static int sip_hangup(struct ast_channel *ast)
append_history(p, needcancel ? "Cancel" : "Hangup", "Cause %s", p->owner ? ast_cause2str(p->hangupcause) : "Unknown");
/* Disconnect */
- if (p->vad)
- ast_dsp_free(p->vad);
+ disable_digit_detect(p);
p->owner = NULL;
ast->tech_pvt = dialog_unref(ast->tech_pvt, "unref ast->tech_pvt");
@@ -6453,7 +6498,6 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
return res;
}
-
/*! \brief Initiate a call in the SIP channel
called from sip_request_call (calls from the pbx ) for outbound channels
and from handle_request_invite for inbound channels
@@ -6552,12 +6596,10 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
else
ast_debug(3, "This channel will not be able to handle video.\n");
- if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
+ if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
+ (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
if (!i->rtp || ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND)) {
- i->vad = ast_dsp_new();
- ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT);
- if (global_relaxdtmf)
- ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
+ enable_digit_detect(i);
}
} else if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) {
if (i->rtp) {
@@ -6853,8 +6895,8 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p
ast_set_write_format(p->owner, p->owner->writeformat);
}
- if (f && (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
- f = ast_dsp_process(p->owner, p->vad, f);
+ if (f && p->dsp) {
+ f = ast_dsp_process(p->owner, p->dsp, f);
if (f && f->frametype == AST_FRAME_DTMF) {
if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && f->subclass == 'f') {
ast_debug(1, "Fax CNG detected on %s\n", ast->name);
@@ -25354,16 +25396,11 @@ static int sip_dtmfmode(struct ast_channel *chan, const char *data)
ast_log(LOG_WARNING, "I don't know about this dtmf mode: %s\n", mode);
if (p->rtp)
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
- if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) {
- if (!p->vad) {
- p->vad = ast_dsp_new();
- ast_dsp_set_features(p->vad, DSP_FEATURE_DIGIT_DETECT);
- }
+ if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
+ (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
+ enable_digit_detect(p);
} else {
- if (p->vad) {
- ast_dsp_free(p->vad);
- p->vad = NULL;
- }
+ disable_digit_detect(p);
}
sip_pvt_unlock(p);
ast_channel_unlock(chan);