No subject
Thu Jul 12 09:23:04 CDT 2007
Modified:
branches/1.2/xpp/card_fxo.c
Modified: branches/1.2/xpp/card_fxo.c
URL: http://svn.digium.com/view/zaptel/branches/1.2/xpp/card_fxo.c?view=diff&rev=4519&r1=4518&r2=4519
==============================================================================
--- branches/1.2/xpp/card_fxo.c (original)
+++ branches/1.2/xpp/card_fxo.c Tue Sep 9 08:00:04 2008
@@ -39,7 +39,7 @@
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]");
/* Backward compatibility plug */
#ifndef ZT_GET_PARAMS_V1
@@ -49,8 +49,8 @@
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) */
@@ -149,6 +149,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];
@@ -304,12 +306,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_zap)
update_zap_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_zap)
@@ -350,7 +354,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);
}
@@ -363,6 +367,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;
}
@@ -466,7 +471,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");
@@ -501,12 +506,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");
#ifdef ZT_SPANSTAT_V2
xpd->span.spantype = "FXO";
@@ -525,6 +532,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;
}
@@ -701,6 +711,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 zt_chan *chan = &xpd->span.chans[portno];
+ int sample;
+ int i;
+
+ for(i = 0; i < ZT_CHUNKSIZE; i++) {
+ sample = ZT_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);
+ zt_qevent_lock(chan, ZT_EVENT_POLARITY);
+ break;
+ }
+ }
+ }
+ }
+}
+
static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
{
struct FXO_priv_data *priv;
@@ -717,6 +777,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;
}
@@ -931,7 +993,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 zaptel-commits
mailing list