From 4ba510314a8dcd24bbcd32af137439c75f4c652f Mon Sep 17 00:00:00 2001 From: tzafrir Date: Sun, 30 Nov 2008 12:10:03 +0000 Subject: xpp: PCM changes and related bugfixes. * Power-denial signalling is now sent to Zaptel to decide if we're LS or KS (and not hang up ourselves always). * Fix card_fxo's caller_id_style=1 (FSK). * Macro XPD_CHAN: s/xpd->chans[i]/XPD_CHAN(xpd, i)/ to reduce diff from DAHDI. git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@4590 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- kernel/xpp/card_fxo.c | 116 ++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 56 deletions(-) (limited to 'kernel/xpp/card_fxo.c') 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, -- cgit v1.2.3