summaryrefslogtreecommitdiff
path: root/kernel/xpp/card_fxo.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/xpp/card_fxo.c')
-rw-r--r--kernel/xpp/card_fxo.c116
1 files changed, 60 insertions, 56 deletions
diff --git a/kernel/xpp/card_fxo.c b/kernel/xpp/card_fxo.c
index 30c9de8..2090773 100644
--- a/kernel/xpp/card_fxo.c
+++ b/kernel/xpp/card_fxo.c
@@ -175,6 +175,27 @@ struct FXO_priv_data {
/*---------------- FXO: Static functions ----------------------------------*/
+static const char *power2str(enum power_state pw)
+{
+ switch(pw) {
+ case POWER_UNKNOWN: return "UNKOWN";
+ case POWER_OFF: return "OFF";
+ case POWER_ON: return "ON";
+ }
+ return NULL;
+}
+
+static void power_change(xpd_t *xpd, int portno, enum power_state pw)
+{
+ struct FXO_priv_data *priv;
+
+ priv = xpd->priv;
+ LINE_DBG(SIGNAL, xpd, portno, "power: %s -> %s\n",
+ power2str(priv->power[portno]),
+ power2str(pw));
+ priv->power[portno] = pw;
+}
+
static void reset_battery_readings(xpd_t *xpd, lineno_t pos)
{
struct FXO_priv_data *priv = xpd->priv;
@@ -265,30 +286,15 @@ static void handle_fxo_leds(xpd_t *xpd)
static void update_zap_ring(xpd_t *xpd, int pos, bool on)
{
- zt_rxsig_t rxsig;
-
BUG_ON(!xpd);
- if(on) {
- if(caller_id_style == CID_STYLE_BELL) {
- LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: off\n");
- BIT_CLR(xpd->cid_on, pos);
- }
- rxsig = ZT_RXSIG_RING;
- } else {
- if(caller_id_style == CID_STYLE_BELL) {
- LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: on\n");
- BIT_SET(xpd->cid_on, pos);
- }
- rxsig = ZT_RXSIG_OFFHOOK;
- }
- pcm_recompute(xpd, 0);
+ if(caller_id_style == CID_STYLE_BELL)
+ oht_pcm(xpd, pos, !on);
/*
* We should not spinlock before calling zt_hooksig() as
* it may call back into our xpp_hooksig() and cause
* a nested spinlock scenario
*/
- if(SPAN_REGISTERED(xpd))
- zt_hooksig(&xpd->chans[pos], rxsig);
+ notify_rxsig(xpd, pos, (on) ? ZT_RXSIG_RING : ZT_RXSIG_OFFHOOK);
}
static void mark_ring(xpd_t *xpd, lineno_t pos, bool on, bool update_zap)
@@ -349,15 +355,9 @@ static int do_sethook(xpd_t *xpd, int pos, bool to_offhook)
else
MARK_OFF(priv, pos, LED_GREEN);
ret = DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, REG_DAA_CONTROL1, value);
- if(to_offhook) {
- BIT_SET(xpd->offhook, pos);
- } else {
- BIT_CLR(xpd->offhook, pos);
- }
- if(caller_id_style != CID_STYLE_ETSI_DTMF) {
- LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: off\n");
- BIT_CLR(xpd->cid_on, pos);
- }
+ mark_offhook(xpd, pos, to_offhook);
+ if(caller_id_style != CID_STYLE_ETSI_DTMF)
+ oht_pcm(xpd, pos, 0);
#ifdef WITH_METERING
priv->metering_count[pos] = 0;
priv->metering_tone_state = 0L;
@@ -366,7 +366,7 @@ static int do_sethook(xpd_t *xpd, int pos, bool to_offhook)
reset_battery_readings(xpd, pos); /* unstable during hook changes */
priv->power_denial_safezone[pos] = (to_offhook) ? POWER_DENIAL_SAFEZONE : 0;
if(!to_offhook)
- priv->power[pos] = POWER_UNKNOWN;
+ power_change(xpd, pos, POWER_UNKNOWN);
priv->cidtimer[pos] = xpd->timer_count;
spin_unlock_irqrestore(&xpd->lock, flags);
return ret;
@@ -469,10 +469,11 @@ static int FXO_card_init(xbus_t *xbus, xpd_t *xpd)
for_each_line(xpd, i) {
do_sethook(xpd, i, 0);
priv->polarity[i] = POL_UNKNOWN; /* will be updated on next battery sample */
+ priv->polarity_debounce[i] = 0;
priv->battery[i] = BATTERY_UNKNOWN; /* will be updated on next battery sample */
priv->power[i] = POWER_UNKNOWN; /* will be updated on next battery sample */
if(caller_id_style == CID_STYLE_ETSI_DTMF)
- BIT_SET(xpd->cid_on, i);
+ oht_pcm(xpd, i, 1);
}
XPD_DBG(GENERAL, xpd, "done\n");
for_each_line(xpd, i) {
@@ -486,7 +487,7 @@ static int FXO_card_init(xbus_t *xbus, xpd_t *xpd)
do_led(xpd, i, LED_GREEN, 0);
msleep(50);
}
- pcm_recompute(xpd, 0);
+ CALL_XMETHOD(card_pcm_recompute, xbus, xpd, 0);
return 0;
}
@@ -519,7 +520,7 @@ static int FXO_card_zaptel_preregistration(xpd_t *xpd, bool on)
xpd->span.spantype = "FXO";
#endif
for_each_line(xpd, i) {
- struct zt_chan *cur_chan = &xpd->chans[i];
+ struct zt_chan *cur_chan = XPD_CHAN(xpd, i);
XPD_DBG(GENERAL, xpd, "setting FXO channel %d\n", i);
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXO/%02d/%1d%1d/%d",
@@ -585,7 +586,6 @@ static int FXO_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
txsig2str(txsig), txsig);
return -EINVAL;
}
- pcm_recompute(xpd, 0);
return ret;
}
@@ -602,11 +602,11 @@ static void zap_report_battery(xpd_t *xpd, lineno_t chan)
break;
case BATTERY_OFF:
LINE_DBG(SIGNAL, xpd, chan, "Send ZT_ALARM_RED\n");
- zt_alarm_channel(&xpd->chans[chan], ZT_ALARM_RED);
+ zt_alarm_channel(XPD_CHAN(xpd, chan), ZT_ALARM_RED);
break;
case BATTERY_ON:
LINE_DBG(SIGNAL, xpd, chan, "Send ZT_ALARM_NONE\n");
- zt_alarm_channel(&xpd->chans[chan], ZT_ALARM_NONE);
+ zt_alarm_channel(XPD_CHAN(xpd, chan), ZT_ALARM_NONE);
break;
}
}
@@ -636,7 +636,7 @@ static void poll_metering(xbus_t *xbus, xpd_t *xpd)
int i;
for_each_line(xpd, i) {
- if (IS_SET(xpd->offhook, i))
+ if (IS_OFFHOOK(xpd, i))
DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_METERING, 0);
}
}
@@ -689,7 +689,7 @@ static void handle_fxo_power_denial(xpd_t *xpd)
DAA_DIRECT_REQUEST(xpd->xbus, xpd, i, DAA_READ, DAA_REG_CURRENT, 0);
}
}
- if(IS_SET(priv->maybe_power_denial, i) && !xpd->ringing[i] && IS_SET(xpd->offhook, i)) {
+ if(IS_SET(priv->maybe_power_denial, i) && !xpd->ringing[i] && IS_OFFHOOK(xpd, i)) {
/*
* Ring detection by the firmware takes some time.
* Therefore we delay our decision until we are
@@ -700,9 +700,10 @@ static void handle_fxo_power_denial(xpd_t *xpd)
LINE_DBG(SIGNAL, xpd, i, "Power Denial Hangup\n");
priv->power_denial_delay[i] = 0;
BIT_CLR(priv->maybe_power_denial, i);
- do_sethook(xpd, i, 0);
- update_line_status(xpd, i, 0);
- pcm_recompute(xpd, 0);
+ /*
+ * Let Asterisk decide what to do
+ */
+ notify_rxsig(xpd, i, ZT_RXSIG_ONHOOK);
}
} else {
priv->power_denial_delay[i] = 0;
@@ -731,7 +732,7 @@ static void check_etsi_dtmf(xpd_t *xpd)
timer_count = xpd->timer_count;
for_each_line(xpd, portno) {
/* Skip offhook and ringing ports */
- if(IS_SET(xpd->offhook, portno) || xpd->ringing[portno])
+ if(IS_OFFHOOK(xpd, portno) || xpd->ringing[portno])
continue;
if(IS_SET(priv->cidfound, portno)) {
if(timer_count > priv->cidtimer[portno] + 4000) {
@@ -743,7 +744,7 @@ static void check_etsi_dtmf(xpd_t *xpd)
continue;
}
if(timer_count > priv->cidtimer[portno] + 400) {
- struct zt_chan *chan = &xpd->span.chans[portno];
+ struct zt_chan *chan = XPD_CHAN(xpd, portno);
int sample;
int i;
@@ -922,8 +923,11 @@ static void update_battery_voltage(xpd_t *xpd, byte data_low, xportno_t portno)
priv->battery[portno] = BATTERY_OFF;
if(SPAN_REGISTERED(xpd))
zap_report_battery(xpd, portno);
- priv->polarity[portno] = POL_UNKNOWN; /* What's the polarity ? */
- priv->power[portno] = POWER_UNKNOWN; /* What's the current ? */
+ /* What's the polarity ? */
+ priv->polarity[portno] = POL_UNKNOWN;
+ priv->polarity_debounce[portno] = 0;
+ /* What's the current ? */
+ power_change(xpd, portno, POWER_UNKNOWN);
/*
* Stop further processing for now
*/
@@ -976,7 +980,7 @@ static void update_battery_voltage(xpd_t *xpd, byte data_low, xportno_t portno)
msec = priv->polarity_debounce[portno]++ * poll_battery_interval;
if (msec >= POLREV_THRESHOLD) {
priv->polarity_debounce[portno] = 0;
- if(pol != POL_UNKNOWN) {
+ if(pol != POL_UNKNOWN && priv->polarity[portno] != POL_UNKNOWN) {
char *polname = NULL;
if(pol == POL_POSITIVE)
@@ -993,14 +997,12 @@ static void update_battery_voltage(xpd_t *xpd, byte data_low, xportno_t portno)
* 2. In some countries used to report caller-id during onhook
* but before first ring.
*/
- if(caller_id_style == CID_STYLE_ETSI_FSK) {
- LINE_DBG(SIGNAL, xpd, portno, "Caller-ID PCM: on\n");
- BIT_SET(xpd->cid_on, portno); /* will be cleared on ring/offhook */
- }
+ if(caller_id_style == CID_STYLE_ETSI_FSK)
+ oht_pcm(xpd, portno, 1); /* will be cleared on ring/offhook */
if(SPAN_REGISTERED(xpd)) {
LINE_DBG(SIGNAL, xpd, portno,
"Send ZT_EVENT_POLARITY: %s\n", polname);
- zt_qevent_lock(&xpd->chans[portno], ZT_EVENT_POLARITY);
+ zt_qevent_lock(XPD_CHAN(xpd, portno), ZT_EVENT_POLARITY);
}
}
priv->polarity[portno] = pol;
@@ -1024,7 +1026,7 @@ static void update_battery_current(xpd_t *xpd, byte data_low, xportno_t portno)
* During ringing, current is not stable.
* During onhook there should not be current anyway.
*/
- if(xpd->ringing[portno] || !IS_SET(xpd->offhook, portno))
+ if(xpd->ringing[portno] || !IS_OFFHOOK(xpd, portno))
goto ignore_it;
/*
* Power denial with no battery voltage is meaningless
@@ -1036,15 +1038,16 @@ static void update_battery_current(xpd_t *xpd, byte data_low, xportno_t portno)
goto ignore_it;
if(data_low < POWER_DENIAL_CURRENT) {
if(priv->power[portno] == POWER_ON) {
- LINE_DBG(SIGNAL, xpd, portno, "power: ON -> OFF\n");
- priv->power[portno] = POWER_OFF;
+ power_change(xpd, portno, POWER_OFF);
priv->power_denial_minimum[portno] = POWER_DENIAL_TIME;
}
} else {
- LINE_DBG(SIGNAL, xpd, portno, "power: ON\n");
- priv->power[portno] = POWER_ON;
- priv->power_denial_minimum[portno] = 0;
- update_line_status(xpd, portno, 1);
+ if(priv->power[portno] != POWER_ON) {
+ power_change(xpd, portno, POWER_ON);
+ priv->power_denial_minimum[portno] = 0;
+ /* We are now OFFHOOK */
+ hookstate_changed(xpd, portno, 1);
+ }
}
return;
ignore_it:
@@ -1135,6 +1138,7 @@ static xproto_table_t PROTO_TABLE(FXO) = {
.card_zaptel_postregistration = FXO_card_zaptel_postregistration,
.card_hooksig = FXO_card_hooksig,
.card_tick = FXO_card_tick,
+ .card_pcm_recompute = generic_card_pcm_recompute,
.card_pcm_fromspan = generic_card_pcm_fromspan,
.card_pcm_tospan = generic_card_pcm_tospan,
.card_ioctl = FXO_card_ioctl,