[svn-commits] tzafrir: linux/trunk r4979 - /linux/trunk/drivers/dahdi/xpp/card_fxo.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Sep 25 06:45:31 CDT 2008
Author: tzafrir
Date: Thu Sep 25 06:45:29 2008
New Revision: 4979
URL: http://svn.digium.com/view/dahdi?view=rev&rev=4979
Log:
XPP FXO: Add caller-id workaround for ESTI-DTMF (for #9096)
* Also rename the CID_STYLE_* constants to formal names.
Modified:
linux/trunk/drivers/dahdi/xpp/card_fxo.c
Modified: linux/trunk/drivers/dahdi/xpp/card_fxo.c
URL: http://svn.digium.com/view/dahdi/linux/trunk/drivers/dahdi/xpp/card_fxo.c?view=diff&rev=4979&r1=4978&r2=4979
==============================================================================
--- linux/trunk/drivers/dahdi/xpp/card_fxo.c (original)
+++ linux/trunk/drivers/dahdi/xpp/card_fxo.c Thu Sep 25 06:45:29 2008
@@ -39,12 +39,12 @@
static DEF_PARM(uint, poll_metering_interval, 500, 0644, "Poll metering interval in milliseconds (0 - disable)");
#endif
static DEF_PARM(int, ring_debounce, 50, 0644, "Number of ticks to debounce a false RING indication");
-static DEF_PARM(int, caller_id_style, 0, 0444, "Caller-Id detection style: 0 - [BELL], 1 - [BT], 2 - [PASS]");
+static DEF_PARM(int, caller_id_style, 0, 0444, "Caller-Id detection style: 0 - [BELL], 1 - [ETSI_FSK], 2 - [ETSI_DTMF]");
enum cid_style {
CID_STYLE_BELL = 0, /* E.g: US (Bellcore) */
- CID_STYLE_ETSI_POLREV = 1, /* E.g: UK (British Telecom) */
- CID_STYLE_PASS_ALWAYS = 2, /* E.g: DK */
+ CID_STYLE_ETSI_FSK = 1, /* E.g: UK (British Telecom) */
+ CID_STYLE_ETSI_DTMF = 2, /* E.g: DK, Russia */
};
/* Signaling is opposite (fxs signalling for fxo card) */
@@ -143,6 +143,8 @@
ushort power_denial_delay[CHANNELS_PERXPD];
ushort power_denial_minimum[CHANNELS_PERXPD];
ushort power_denial_safezone[CHANNELS_PERXPD];
+ xpp_line_t cidfound; /* 0 - OFF, 1 - ON */
+ unsigned int cidtimer[CHANNELS_PERXPD];
xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */
xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */
int led_counter[NUM_LEDS][CHANNELS_PERXPD];
@@ -298,12 +300,14 @@
if(on && !xpd->ringing[pos]) {
LINE_DBG(SIGNAL, xpd, pos, "START\n");
xpd->ringing[pos] = 1;
+ priv->cidtimer[pos] = xpd->timer_count;
MARK_BLINK(priv, pos, LED_GREEN, LED_BLINK_RING);
if(update_dahdi)
update_dahdi_ring(xpd, pos, on);
} else if(!on && xpd->ringing[pos]) {
LINE_DBG(SIGNAL, xpd, pos, "STOP\n");
xpd->ringing[pos] = 0;
+ priv->cidtimer[pos] = xpd->timer_count;
if(IS_BLINKING(priv, pos, LED_GREEN))
MARK_BLINK(priv, pos, LED_GREEN, 0);
if(update_dahdi)
@@ -344,7 +348,7 @@
} else {
BIT_CLR(xpd->offhook, pos);
}
- if(caller_id_style != CID_STYLE_PASS_ALWAYS) {
+ if(caller_id_style != CID_STYLE_ETSI_DTMF) {
LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: off\n");
BIT_CLR(xpd->cid_on, pos);
}
@@ -357,6 +361,7 @@
priv->power_denial_safezone[pos] = (to_offhook) ? POWER_DENIAL_SAFEZONE : 0;
if(!to_offhook)
priv->power[pos] = POWER_UNKNOWN;
+ priv->cidtimer[pos] = xpd->timer_count;
spin_unlock_irqrestore(&xpd->lock, flags);
return ret;
}
@@ -460,7 +465,7 @@
priv->polarity[i] = POL_UNKNOWN; /* will be updated on next battery sample */
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_PASS_ALWAYS)
+ if(caller_id_style == CID_STYLE_ETSI_DTMF)
BIT_SET(xpd->cid_on, i);
}
XPD_DBG(GENERAL, xpd, "done\n");
@@ -495,12 +500,14 @@
xbus_t *xbus;
struct FXO_priv_data *priv;
int i;
+ unsigned int timer_count;
BUG_ON(!xpd);
xbus = xpd->xbus;
BUG_ON(!xbus);
priv = xpd->priv;
BUG_ON(!priv);
+ timer_count = xpd->timer_count;
XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF");
xpd->span.spantype = "FXO";
for_each_line(xpd, i) {
@@ -517,6 +524,9 @@
MARK_ON(priv, i, LED_GREEN);
msleep(4);
MARK_ON(priv, i, LED_RED);
+ }
+ for_each_line(xpd, i) {
+ priv->cidtimer[i] = timer_count;
}
return 0;
}
@@ -693,6 +703,56 @@
}
}
+/*
+ * For caller-id CID_STYLE_ETSI_DTMF:
+ * - No indication is passed before the CID
+ * - We try to detect it and send "fake" polarity reversal.
+ * - The zapata.conf should have cidstart=polarity
+ * - Based on an idea in http://bugs.digium.com/view.php?id=9096
+ */
+static void check_etsi_dtmf(xpd_t *xpd)
+{
+ struct FXO_priv_data *priv;
+ int portno;
+ unsigned int timer_count;
+
+ if(!SPAN_REGISTERED(xpd))
+ return;
+ priv = xpd->priv;
+ BUG_ON(!priv);
+ timer_count = xpd->timer_count;
+ for_each_line(xpd, portno) {
+ /* Skip offhook and ringing ports */
+ if(IS_SET(xpd->offhook, portno) || xpd->ringing[portno])
+ continue;
+ if(IS_SET(priv->cidfound, portno)) {
+ if(timer_count > priv->cidtimer[portno] + 4000) {
+ /* reset flags if it's been a while */
+ priv->cidtimer[portno] = timer_count;
+ BIT_CLR(priv->cidfound, portno);
+ LINE_DBG(SIGNAL, xpd, portno, "Reset CID flag\n");
+ }
+ continue;
+ }
+ if(timer_count > priv->cidtimer[portno] + 400) {
+ struct dahdi_chan *chan = xpd->span.chans[portno];
+ int sample;
+ int i;
+
+ for(i = 0; i < DAHDI_CHUNKSIZE; i++) {
+ sample = DAHDI_XLAW(chan->readchunk[i], chan);
+ if(sample > 16000 || sample < -16000) {
+ priv->cidtimer[portno] = timer_count;
+ BIT_SET(priv->cidfound, portno);
+ LINE_DBG(SIGNAL, xpd, portno, "Found DTMF CLIP (%d)\n", i);
+ dahdi_qevent_lock(chan, DAHDI_EVENT_POLARITY);
+ break;
+ }
+ }
+ }
+ }
+}
+
static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
{
struct FXO_priv_data *priv;
@@ -709,6 +769,8 @@
handle_fxo_leds(xpd);
handle_fxo_ring(xpd);
handle_fxo_power_denial(xpd);
+ if(caller_id_style == CID_STYLE_ETSI_DTMF && likely(xpd->card_present))
+ check_etsi_dtmf(xpd);
priv->poll_counter++;
return 0;
}
@@ -923,7 +985,7 @@
* 2. In some countries used to report caller-id during onhook
* but before first ring.
*/
- if(caller_id_style == CID_STYLE_ETSI_POLREV) {
+ 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 */
}
More information about the svn-commits
mailing list