aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
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);