summaryrefslogtreecommitdiff
path: root/channels/sig_analog.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2010-11-24 22:52:07 +0000
committerRichard Mudgett <rmudgett@digium.com>2010-11-24 22:52:07 +0000
commitccdc417ab57102d11d055dbaec943bf6adfdd337 (patch)
tree22b95a7e3536d461b8b29dd4af3fbdb6b0f5ddde /channels/sig_analog.c
parentddd0ae53d23f432a16e01a603120d8ff97ea53a4 (diff)
Merged revisions 296167 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8 ................ r296167 | rmudgett | 2010-11-24 16:49:48 -0600 (Wed, 24 Nov 2010) | 57 lines Merged revisions 296166 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.6.2 ................ r296166 | rmudgett | 2010-11-24 16:42:45 -0600 (Wed, 24 Nov 2010) | 50 lines Merged revisions 296165 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r296165 | rmudgett | 2010-11-24 16:41:07 -0600 (Wed, 24 Nov 2010) | 43 lines Oneway audio to SIP phone from FXS port after FXS port gets a CallWaiting pip. The FXS connected phone has to have CW/CID support to fail, as it will send back a DTMF 'A' or 'D' when it's ready to receive CallerID. A normal phone with no CID never fails. Also the SIP phone does not hear MOH when the CW call is answered. The DTMF end frame is suppressed when the phone acknowledges the CW signal for CID. The problem is the DTMF begin frame needs to be suppressed as well. The DTMF begin frame is causing SIP to start sending the DTMF RTP frames. Since the DTMF end frame is suppressed, SIP will not stop sending those DTMF RTP packets. * Suppress the DTMF begin and end frames when the channel driver is looking for DTMF digits. * Fixed a couple issues caused by not cleaning up the CID spill if you answer the CW call while it is sending the CID spill. * Fixed not sending CW/CID spill to the phone when the call is natively bridged. (Fixed by not using native bridge if CW/CID is possible.) * Suppress received audio when sending CW/CID spills. The other parties involved do not need to hear the CW/CID spills and may be confused if the CW call is for them. (closes issue #18129) Reported by: alecdavis Patches: issue_18129_v1.8_v3.patch uploaded by rmudgett (license 664) Tested by: alecdavis, rmudgett NOTE: * v1.4 does not have the main problem fixed by suppressing the DTMF start frames. The other three items fixed are relevant. * If you really must restore native bridging between analog ports, you need to disable CW/CID either by configuring chan_dahdi.conf callwaitingcallerid=no or dialing *70 before dialing the number to temporarily disable CW. ........ ................ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@296168 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/sig_analog.c')
-rw-r--r--channels/sig_analog.c84
1 files changed, 53 insertions, 31 deletions
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index ba6ed45c8..7c35f6b5e 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -624,10 +624,10 @@ static int analog_dsp_set_digitmode(struct analog_pvt *p, enum analog_dsp_digitm
return -1;
}
-static void analog_cb_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
+static void analog_cb_handle_dtmf(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
{
- if (p->calls->handle_dtmfup) {
- p->calls->handle_dtmfup(p->chan_pvt, ast, analog_index, dest);
+ if (p->calls->handle_dtmf) {
+ p->calls->handle_dtmf(p->chan_pvt, ast, analog_index, dest);
}
}
@@ -859,10 +859,7 @@ int analog_available(struct analog_pvt *p)
static int analog_stop_callwait(struct analog_pvt *p)
{
- if (p->callwaitingcallerid) {
- p->callwaitcas = 0;
- }
-
+ p->callwaitcas = 0;
if (p->calls->stop_callwait) {
return p->calls->stop_callwait(p->chan_pvt);
}
@@ -871,15 +868,21 @@ static int analog_stop_callwait(struct analog_pvt *p)
static int analog_callwait(struct analog_pvt *p)
{
- if (p->callwaitingcallerid) {
- p->callwaitcas = 1;
- }
+ p->callwaitcas = p->callwaitingcallerid;
if (p->calls->callwait) {
return p->calls->callwait(p->chan_pvt);
}
return 0;
}
+static void analog_set_callwaiting(struct analog_pvt *p, int callwaiting_enable)
+{
+ p->callwaiting = callwaiting_enable;
+ if (p->calls->set_callwaiting) {
+ p->calls->set_callwaiting(p->chan_pvt, callwaiting_enable);
+ }
+}
+
static void analog_set_cadence(struct analog_pvt *p, struct ast_channel *chan)
{
if (p->calls->set_cadence) {
@@ -1456,7 +1459,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
p->callwaitcas = 0;
- p->callwaiting = p->permcallwaiting;
+ analog_set_callwaiting(p, p->permcallwaiting);
p->hidecallerid = p->permhidecallerid;
analog_set_dialing(p, 0);
analog_update_conf(p);
@@ -1574,35 +1577,45 @@ static int analog_handles_digit(struct ast_frame *f)
}
}
-void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub idx, struct ast_frame **dest)
+void analog_handle_dtmf(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub idx, struct ast_frame **dest)
{
struct ast_frame *f = *dest;
- ast_debug(1, "DTMF digit: %c on %s\n", f->subclass.integer, ast->name);
+ ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
+ f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
+ f->subclass.integer, f->subclass.integer, ast->name);
if (analog_check_confirmanswer(p)) {
- ast_debug(1, "Confirm answer on %s!\n", ast->name);
- /* Upon receiving a DTMF digit, consider this an answer confirmation instead
- of a DTMF digit */
- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
- p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
+ if (f->frametype == AST_FRAME_DTMF_END) {
+ ast_debug(1, "Confirm answer on %s!\n", ast->name);
+ /* Upon receiving a DTMF digit, consider this an answer confirmation instead
+ of a DTMF digit */
+ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+ p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
+ /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
+ analog_set_confirmanswer(p, 0);
+ } else {
+ p->subs[idx].f.frametype = AST_FRAME_NULL;
+ p->subs[idx].f.subclass.integer = 0;
+ }
*dest = &p->subs[idx].f;
- /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
- analog_set_confirmanswer(p, 0);
} else if (p->callwaitcas) {
- if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
- ast_debug(1, "Got some DTMF, but it's for the CAS\n");
- p->caller.id.name.str = p->callwait_name;
- p->caller.id.number.str = p->callwait_num;
- analog_send_callerid(p, 1, &p->caller);
+ if (f->frametype == AST_FRAME_DTMF_END) {
+ if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
+ ast_debug(1, "Got some DTMF, but it's for the CAS\n");
+ p->caller.id.name.str = p->callwait_name;
+ p->caller.id.number.str = p->callwait_num;
+ analog_send_callerid(p, 1, &p->caller);
+ }
+ if (analog_handles_digit(f)) {
+ p->callwaitcas = 0;
+ }
}
- if (analog_handles_digit(f))
- p->callwaitcas = 0;
p->subs[idx].f.frametype = AST_FRAME_NULL;
p->subs[idx].f.subclass.integer = 0;
*dest = &p->subs[idx].f;
} else {
- analog_cb_handle_dtmfup(p, ast, idx, dest);
+ analog_cb_handle_dtmf(p, ast, idx, dest);
}
}
@@ -2122,7 +2135,7 @@ static void *__analog_ss_thread(void *data)
} else if (p->callwaiting && !strcmp(exten, "*70")) {
ast_verb(3, "Disabling call waiting on %s\n", chan->name);
/* Disable call waiting if enabled */
- p->callwaiting = 0;
+ analog_set_callwaiting(p, 0);
res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
if (res) {
ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
@@ -2631,7 +2644,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
analog_confmute(p, 0);
p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
p->subs[idx].f.subclass.integer = res & 0xff;
- analog_handle_dtmfup(p, ast, idx, &f);
+ analog_handle_dtmf(p, ast, idx, &f);
return f;
}
@@ -2641,6 +2654,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
analog_confmute(p, 1);
p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
p->subs[idx].f.subclass.integer = res & 0xff;
+ analog_handle_dtmf(p, ast, idx, &f);
return f;
}
@@ -2890,7 +2904,10 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
analog_set_needringing(p, 0);
analog_off_hook(p);
ast_debug(1, "channel %d answered\n", p->channel);
+
+ /* Cancel any running CallerID spill */
analog_cancel_cidspill(p);
+
analog_set_dialing(p, 0);
p->callwaitcas = 0;
if (analog_check_confirmanswer(p)) {
@@ -3050,6 +3067,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
idx, analog_get_sub_fd(p, ANALOG_SUB_REAL), analog_get_sub_fd(p, ANALOG_SUB_CALLWAIT), analog_get_sub_fd(p, ANALOG_SUB_THREEWAY));
+ /* Cancel any running CallerID spill */
+ analog_cancel_cidspill(p);
p->callwaitcas = 0;
if (idx != ANALOG_SUB_REAL) {
@@ -3568,7 +3587,10 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
if (res && (errno == EBUSY)) {
break;
}
+
+ /* Cancel VMWI spill */
analog_cancel_cidspill(i);
+
if (i->immediate) {
analog_set_echocanceller(i, 1);
/* The channel is immediately up. Start right away */
@@ -3826,7 +3848,7 @@ int analog_config_complete(struct analog_pvt *p)
p->permcallwaiting = 0;
}
- p->callwaiting = p->permcallwaiting;
+ analog_set_callwaiting(p, p->permcallwaiting);
return 0;
}