diff options
Diffstat (limited to 'xpp/card_fxo.c')
-rw-r--r-- | xpp/card_fxo.c | 99 |
1 files changed, 55 insertions, 44 deletions
diff --git a/xpp/card_fxo.c b/xpp/card_fxo.c index 513cd5b..cbe953b 100644 --- a/xpp/card_fxo.c +++ b/xpp/card_fxo.c @@ -55,7 +55,6 @@ enum fxo_leds { #define NUM_LEDS 1 #define DELAY_UNTIL_DIALTONE 3000 -#define POLREV_START 3 /* time after offhook to ignore polarity reversals (in ticks) */ #define POLREV_THRESHOLD 1000 /* minimum duration for polarity reversal detection (in ticks) */ #define BAT_THRESHOLD 3 #define BAT_DEBOUNCE 1000 /* compensate for battery voltage fluctuation (in ticks) */ @@ -105,11 +104,11 @@ struct FXO_priv_data { #endif struct proc_dir_entry *fxo_info; uint poll_counter; + signed char battery_voltage[CHANNELS_PERXPD]; xpp_line_t battery; ushort battery_debounce[CHANNELS_PERXPD]; xpp_line_t polarity; ushort polarity_counter[CHANNELS_PERXPD]; - uint offhook_timestamp[CHANNELS_PERXPD]; ushort current_counter[CHANNELS_PERXPD]; xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */ @@ -280,7 +279,6 @@ static int do_sethook(xpd_t *xpd, int pos, bool to_offhook) ret = DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_REG_RING, value); if(to_offhook) { BIT_SET(xpd->offhook, pos); - priv->offhook_timestamp[pos] = priv->poll_counter; } else { BIT_CLR(xpd->offhook, pos); BIT_CLR(xpd->cid_on, pos); @@ -709,14 +707,21 @@ HANDLER_DEF(FXO, SIG_CHANGED) return 0; } +#ifndef ZT_GET_PARAMS_V1 +#define zt_alarm_channel(a,b) zt_qevent_lock(a,( (b)==ZT_ALARM_NONE )? \ + ZT_EVENT_NOALARM : ZT_EVENT_ALARM) +#endif static void update_battery_status(xpd_t *xpd, byte data_low, lineno_t chipsel) { struct FXO_priv_data *priv; byte bat = abs((signed char)data_low); byte pol = IS_SET(data_low, 7); + int msec; + priv = xpd->priv; BUG_ON(!priv); + priv->battery_voltage[chipsel] = data_low; if(bat < BAT_THRESHOLD) { /* * Check for battery voltage fluctuations @@ -725,12 +730,12 @@ static void update_battery_status(xpd_t *xpd, byte data_low, lineno_t chipsel) int milliseconds; milliseconds = priv->battery_debounce[chipsel]++ * - poll_battery_interval; + poll_battery_interval; if(milliseconds > BAT_DEBOUNCE) { LINE_DBG(SIGNAL, xpd, chipsel, "BATTERY OFF voltage=%d\n", bat); BIT_CLR(priv->battery, chipsel); if(SPAN_REGISTERED(xpd)) - zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_ALARM); + zt_alarm_channel(&xpd->chans[chipsel], ZT_ALARM_RED); } } @@ -740,45 +745,47 @@ static void update_battery_status(xpd_t *xpd, byte data_low, lineno_t chipsel) LINE_DBG(SIGNAL, xpd, chipsel, "BATTERY ON voltage=%d\n", bat); BIT_SET(priv->battery, chipsel); if(SPAN_REGISTERED(xpd)) - zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_NOALARM); + zt_alarm_channel(&xpd->chans[chipsel], ZT_ALARM_NONE); } } /* * Handle reverse polarity */ - if (IS_SET(xpd->offhook, chipsel)) { /* Learn the current polarity */ - if (priv->poll_counter - priv->offhook_timestamp[chipsel] < POLREV_START) { - priv->polarity_counter[chipsel] = 0; - if (pol) - BIT_SET(priv->polarity, chipsel); - else - BIT_CLR(priv->polarity, chipsel); - } else if (IS_SET(priv->polarity, chipsel) != pol) { /* Polarity has reversed */ - int milliseconds; - - milliseconds = priv->polarity_counter[chipsel]++ * poll_battery_interval; - if (milliseconds >= POLREV_THRESHOLD) { - if (pol) - BIT_SET(priv->polarity, chipsel); - else - BIT_CLR(priv->polarity, chipsel); - priv->polarity_counter[chipsel] = 0; - /* Inform Zaptel */ - LINE_DBG(SIGNAL, xpd, chipsel, "Send ZT_EVENT_POLARITY\n"); - zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_POLARITY); + if(IS_SET(priv->polarity, chipsel) == pol) { + /* same, same, nothing to see here, move on */ + priv->polarity_counter[chipsel] = 0; + return; + } + /* + * Track polarity reversals and debounce spikes. + * Only reversals with long duration count. + */ + msec = priv->polarity_counter[chipsel]++ * poll_battery_interval; + if (msec >= POLREV_THRESHOLD) { + LINE_DBG(SIGNAL, xpd, chipsel, "Polarity is %s\n", + (pol)?"Positive":"Negative"); + priv->polarity_counter[chipsel] = 0; + if (pol) + BIT_SET(priv->polarity, chipsel); + else + BIT_CLR(priv->polarity, chipsel); + /* polarity reversal during offhook should be reported to zaptel */ + if(IS_SET(xpd->offhook, chipsel)) { + /* Inform Zaptel */ + LINE_DBG(SIGNAL, xpd, chipsel, "Send ZT_EVENT_POLARITY\n"); + zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_POLARITY); #if 0 - /* - * These two lines hangup the channel (by sending a message to - * the firmware), and inform Zaptel that the line has been hung-up. - * They are not needed if Asterisk does the hangup after receiving - * a notification from Zaptel (which is sent by the above zt_qevent_lock(). - * Asterisk does that if it has "hanguponpolarityswitch=1" in zapata.conf. - */ - do_sethook(xpd, chipsel, 0); - update_line_status(xpd, chipsel, 0); - pcm_recompute(xpd, 0); + /* + * These two lines hangup the channel (by sending a message to + * the firmware), and inform Zaptel that the line has been hung-up. + * They are not needed if Asterisk does the hangup after receiving + * a notification from Zaptel (which is sent by the above zt_qevent_lock(). + * Asterisk does that if it has "hanguponpolarityswitch=1" in zapata.conf. + */ + do_sethook(xpd, chipsel, 0); + update_line_status(xpd, chipsel, 0); + pcm_recompute(xpd, 0); #endif - } } } } @@ -931,34 +938,38 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count, in len += sprintf(page + len, "\t%-17s: ", "Channel"); for_each_line(xpd, i) { if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%2d ", i % 10); + len += sprintf(page + len, "%3d ", i % 10); } len += sprintf(page + len, "\n\t%-17s: ", "ledstate"); for_each_line(xpd, i) { if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%2d ", IS_SET(priv->ledstate[LED_GREEN], i)); + len += sprintf(page + len, "%3d ", IS_SET(priv->ledstate[LED_GREEN], i)); } len += sprintf(page + len, "\n\t%-17s: ", "blinking"); for_each_line(xpd, i) { if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%2d ", IS_BLINKING(priv,i,LED_GREEN)); + len += sprintf(page + len, "%3d ", IS_BLINKING(priv,i,LED_GREEN)); } len += sprintf(page + len, "\n\t%-17s: ", "battery"); for_each_line(xpd, i) { - len += sprintf(page + len, "%2d ", IS_SET(priv->battery, i)); + len += sprintf(page + len, "%3d ", IS_SET(priv->battery, i)); } len += sprintf(page + len, "\n\t%-17s: ", "polarity"); for_each_line(xpd, i) { - len += sprintf(page + len, "%2d ", IS_SET(priv->polarity, i)); + len += sprintf(page + len, "%3d ", IS_SET(priv->polarity, i)); } len += sprintf(page + len, "\n\t%-17s: ", "polarity_counter"); for_each_line(xpd, i) { - len += sprintf(page + len, "%2d ", priv->polarity_counter[i]); + len += sprintf(page + len, "%3d ", priv->polarity_counter[i]); + } + len += sprintf(page + len, "\n\t%-17s: ", "battery_voltage"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%3d ", priv->battery_voltage[i]); } #ifdef WITH_METERING len += sprintf(page + len, "\n\t%-17s: ", "metering"); for_each_line(xpd, i) { - len += sprintf(page + len, "%2d ", priv->metering_count[i]); + len += sprintf(page + len, "%3d ", priv->metering_count[i]); } #endif len += sprintf(page + len, "\n"); |