summaryrefslogtreecommitdiff
path: root/xpp/card_fxo.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/card_fxo.c')
-rw-r--r--xpp/card_fxo.c99
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");