aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authoralecdavis <alecdavis@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-22 23:14:50 +0000
committeralecdavis <alecdavis@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-22 23:14:50 +0000
commitf4110f5c77863958065979fab4027770ea2990c7 (patch)
tree46a9b237320ec45b34bbc4c57965d79679fb8688 /channels
parent14194cacf54fca15caba5c92e71d0268525897d6 (diff)
Support FXS module Polarity Reversal on remote party Answer and Hangup
FXS lines normally connect to a telephone. However, when FXS lines are routed to an external PBX or Key System to act as "external" or "CO" lines, it is extremely difficult, if not impossible for the external PBX to know when the call has been disconnected without receiving a polarity reversal on the line. Now using answeronpolarityswitch and hanguponpolarityswitch keywords that previously were used only for FXO ports, now applies like functionality for an FXS port, but from the connected equipment's point of view. (closes issue #17318) Reported by: armeniki Patches: fxs_linepolarity.diff5.txt uploaded by alecdavis (license 585) Tested by: alecdavis Review: https://reviewboard.asterisk.org/r/797/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@278809 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_dahdi.c50
-rw-r--r--channels/sig_analog.c47
-rw-r--r--channels/sig_analog.h8
3 files changed, 104 insertions, 1 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 85855e6a4..d2a567135 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -2737,6 +2737,52 @@ static void my_set_needringing(void *pvt, int value)
p->subs[SUB_REAL].needringing = value;
}
+static void my_set_polarity(void *pvt, int value)
+{
+ struct dahdi_pvt *p = pvt;
+
+ if (p->channel == CHAN_PSEUDO) {
+ return;
+ }
+ p->polarity = value;
+ ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
+}
+
+static void my_start_polarityswitch(void *pvt)
+{
+ struct dahdi_pvt *p = pvt;
+
+ if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
+ my_set_polarity(pvt, 0);
+ }
+}
+
+static void my_answer_polarityswitch(void *pvt)
+{
+ struct dahdi_pvt *p = pvt;
+
+ if (!p->answeronpolarityswitch) {
+ return;
+ }
+
+ my_set_polarity(pvt, 1);
+}
+
+static void my_hangup_polarityswitch(void *pvt)
+{
+ struct dahdi_pvt *p = pvt;
+
+ if (!p->hanguponpolarityswitch) {
+ return;
+ }
+
+ if (p->answeronpolarityswitch) {
+ my_set_polarity(pvt, 0);
+ } else {
+ my_set_polarity(pvt, 1);
+ }
+}
+
static int my_start(void *pvt)
{
struct dahdi_pvt *p = pvt;
@@ -3454,6 +3500,10 @@ static struct analog_callback dahdi_analog_callbacks =
.set_pulsedial = my_set_pulsedial,
.get_orig_dialstring = my_get_orig_dialstring,
.set_needringing = my_set_needringing,
+ .set_polarity = my_set_polarity,
+ .start_polarityswitch = my_start_polarityswitch,
+ .answer_polarityswitch = my_answer_polarityswitch,
+ .hangup_polarityswitch = my_hangup_polarityswitch,
};
/*! Round robin search locations. */
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index 68677f561..3214681bd 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -537,6 +537,35 @@ static void analog_set_needringing(struct analog_pvt *p, int value)
}
}
+#if 0
+static void analog_set_polarity(struct analog_pvt *p, int value)
+{
+ if (p->calls->set_polarity) {
+ return p->calls->set_polarity(p->chan_pvt, value);
+ }
+}
+#endif
+
+static void analog_start_polarityswitch(struct analog_pvt *p)
+{
+ if (p->calls->start_polarityswitch) {
+ return p->calls->start_polarityswitch(p->chan_pvt);
+ }
+}
+static void analog_answer_polarityswitch(struct analog_pvt *p)
+{
+ if (p->calls->answer_polarityswitch) {
+ return p->calls->answer_polarityswitch(p->chan_pvt);
+ }
+}
+
+static void analog_hangup_polarityswitch(struct analog_pvt *p)
+{
+ if (p->calls->hangup_polarityswitch) {
+ return p->calls->hangup_polarityswitch(p->chan_pvt);
+ }
+}
+
static int analog_dsp_set_digitmode(struct analog_pvt *p, enum analog_dsp_digitmode mode)
{
if (p->calls->dsp_set_digitmode) {
@@ -1269,6 +1298,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
case ANALOG_SIG_FXOKS:
/* If they're off hook, try playing congestion */
if (analog_is_off_hook(p)) {
+ analog_hangup_polarityswitch(p);
analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
} else {
analog_play_tone(p, ANALOG_SUB_REAL, -1);
@@ -1360,9 +1390,21 @@ int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
p->owner = p->subs[ANALOG_SUB_REAL].owner;
}
}
- if ((p->sig == ANALOG_SIG_FXSLS) || (p->sig == ANALOG_SIG_FXSKS) || (p->sig == ANALOG_SIG_FXSGS)) {
+
+ switch (p->sig) {
+ case ANALOG_SIG_FXSLS:
+ case ANALOG_SIG_FXSKS:
+ case ANALOG_SIG_FXSGS:
analog_set_echocanceller(p, 1);
analog_train_echocanceller(p);
+ break;
+ case ANALOG_SIG_FXOLS:
+ case ANALOG_SIG_FXOKS:
+ case ANALOG_SIG_FXOGS:
+ analog_answer_polarityswitch(p);
+ break;
+ default:
+ break;
}
break;
default:
@@ -2524,6 +2566,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
case ANALOG_SIG_FXOLS:
case ANALOG_SIG_FXOGS:
case ANALOG_SIG_FXOKS:
+ analog_start_polarityswitch(p);
p->fxsoffhookstate = 0;
p->onhooktime = time(NULL);
p->msgstate = -1;
@@ -2705,6 +2748,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
ast_setstate(ast, AST_STATE_DIALING);
} else {
ast_setstate(ast, AST_STATE_UP);
+ analog_answer_polarityswitch(p);
}
return &p->subs[index].f;
case AST_STATE_DOWN:
@@ -3443,6 +3487,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
case ANALOG_SIG_FXOLS:
case ANALOG_SIG_FXOGS:
i->fxsoffhookstate = 0;
+ analog_start_polarityswitch(i);
case ANALOG_SIG_FEATD:
case ANALOG_SIG_FEATDMF:
case ANALOG_SIG_FEATDMF_TA:
diff --git a/channels/sig_analog.h b/channels/sig_analog.h
index e7f1ae2be..ff62ed52d 100644
--- a/channels/sig_analog.h
+++ b/channels/sig_analog.h
@@ -147,6 +147,14 @@ struct analog_callback {
/*! \brief Set channel off hook */
int (* const off_hook)(void *pvt);
void (* const set_needringing)(void *pvt, int value);
+ /*! \brief Set FXS line polarity to 0=IDLE NZ=REVERSED */
+ void (* const set_polarity)(void *pvt, int value);
+ /*! \brief Reset FXS line polarity to IDLE, based on answeronpolarityswitch and hanguponpolarityswitch */
+ void (* const start_polarityswitch)(void *pvt);
+ /*! \brief Switch FXS line polarity, based on answeronpolarityswitch=yes */
+ void (* const answer_polarityswitch)(void *pvt);
+ /*! \brief Switch FXS line polarity, based on answeronpolarityswitch and hanguponpolarityswitch */
+ void (* const hangup_polarityswitch)(void *pvt);
/* We're assuming that we're going to only wink on ANALOG_SUB_REAL - even though in the code there's an argument to the index
* function */
int (* const wink)(void *pvt, enum analog_sub sub);