summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordbailey <dbailey@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-08-13 19:06:04 +0000
committerdbailey <dbailey@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-08-13 19:06:04 +0000
commit29c38b862560126b6bd9150838be7c422f4f321d (patch)
tree5e36a927f3a2ec330e5d60e9bebbdcfe696d90f1
parent72fc3a889c8cf027e8df011c4b6a612c00fb6767 (diff)
Port in the NEON MWI detection from the AA50 into the wctdm24xxp driver
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@4479 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rw-r--r--kernel/wctdm24xxp/base.c138
-rw-r--r--kernel/wctdm24xxp/wctdm24xxp.h6
2 files changed, 124 insertions, 20 deletions
diff --git a/kernel/wctdm24xxp/base.c b/kernel/wctdm24xxp/base.c
index bfd40b5..1de74da 100644
--- a/kernel/wctdm24xxp/base.c
+++ b/kernel/wctdm24xxp/base.c
@@ -193,6 +193,17 @@ static int nativebridge = 0;
static int ringdebounce = DEFAULT_RING_DEBOUNCE;
static int fwringdetect = 0;
static int latency = VOICEBUS_DEFAULT_LATENCY;
+
+#define NEONMWI_ON_DEBOUNCE (3)
+#define MS_PER_HOOKCHECK (1)
+
+static int neonmwi_monitor = 0; /* Note: this causes use of full wave ring detect */
+static int neonmwi_level = 75; /* neon mwi trip voltage */
+static int neonmwi_envelope = 10;
+static int neonmwi_offlimit = 16000; /* Time in milliseconds the monitor is checked before saying no message is waiting */
+
+static int neonmwi_offlimit_cycles; /* Time in milliseconds the monitor is checked before saying no message is waiting */
+
#ifdef VPM_SUPPORT
static int vpmsupport = 1;
static int vpmdtmfsupport = 0;
@@ -1130,6 +1141,7 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card)
unsigned char res;
signed char b;
struct fxo *fxo = &wc->mods[card].fxo;
+ unsigned int abs_voltage;
/* Try to track issues that plague slot one FXO's */
b = wc->cmdq[card].isrshadow[0]; /* Hook/Ring state */
@@ -1142,29 +1154,52 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card)
wctdm_setreg_intr(wc, card, 5, 0x8);
}
if (!fxo->offhook) {
- if (fwringdetect) {
+ if(fwringdetect || neonmwi_monitor) {
+ /* Look for ring status bits (Ring Detect Signal Negative and
+ * Ring Detect Signal Positive) to transition back and forth
+ * some number of times to indicate that a ring is occurring.
+ * Provide some number of samples to allow for the transitions
+ * to occur before ginving up.
+ * NOTE: neon mwi voltages will trigger one of these bits to go active
+ * but not to have transitions between the two bits (i.e. no negative
+ * to positive or positive to negative transversals )
+ */
res = wc->cmdq[card].isrshadow[0] & 0x60;
- if (fxo->ringdebounce--) {
- if (res && (res != fxo->lastrdtx) && (fxo->battery == 1)) {
- if (!fxo->wasringing) {
+ if (0 == wc->mods[card].fxo.wasringing) {
+ if (res) {
+ /* Look for positive/negative crossings in ring status reg */
+ fxo->wasringing = 2;
+ fxo->ringdebounce = ringdebounce /16;
+ fxo->lastrdtx = res;
+ fxo->lastrdtx_count = 0;
+ }
+ } else if (2 == fxo->wasringing) {
+ /* If ring detect signal has transversed */
+ if (res && res != fxo->lastrdtx) {
+ /* if there are at least 3 ring polarity transversals */
+ if(++fxo->lastrdtx_count >= 2) {
fxo->wasringing = 1;
if (debug)
- printk("RING on %d/%d!\n", wc->span.spanno, card + 1);
+ printk("FW RING on %d/%d!\n", wc->span.spanno, card + 1);
zt_hooksig(&wc->chans[card], ZT_RXSIG_RING);
+ fxo->ringdebounce = ringdebounce / 16;
+ } else {
+ fxo->lastrdtx = res;
+ fxo->ringdebounce = ringdebounce / 16;
}
- fxo->lastrdtx = res;
- fxo->ringdebounce = 10;
- } else if (!res) {
- if ((fxo->ringdebounce == 0) && fxo->wasringing) {
- fxo->wasringing = 0;
- if (debug)
- printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1);
- zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
- }
+ /* ring indicator (positve or negative) has not transitioned, check debounce count */
+ } else if (--fxo->ringdebounce == 0) {
+ fxo->wasringing = 0;
+ }
+ } else { /* I am in ring state */
+ if (res) { /* If any ringdetect bits are still active */
+ fxo->ringdebounce = ringdebounce / 16;
+ } else if (--fxo->ringdebounce == 0) {
+ fxo->wasringing = 0;
+ if (debug)
+ printk("FW NO RING on %d/%d!\n", wc->span.spanno, card + 1);
+ zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
}
- } else if (res && (fxo->battery == BATTERY_PRESENT)) {
- fxo->lastrdtx = res;
- fxo->ringdebounce = 10;
}
} else {
res = wc->cmdq[card].isrshadow[0];
@@ -1196,6 +1231,7 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card)
}
b = wc->cmdq[card].isrshadow[1]; /* Voltage */
+ abs_voltage = abs(b);
if (fxovoltage) {
if (!(wc->intcount % 100)) {
@@ -1204,7 +1240,7 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card)
}
}
- if (abs(b) < battthresh) {
+ if (abs_voltage < battthresh) {
/* possible existing states:
battery lost, no debounce timer
battery lost, debounce timer (going to battery present)
@@ -1324,6 +1360,48 @@ static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card)
}
}
}
+
+ /* Look for neon mwi pulse */
+ if (neonmwi_monitor && !wc->mods[card].fxo.offhook) {
+ /* Look for 4 consecutive voltage readings
+ * where the voltage is over the neon limit but
+ * does not vary greatly from the last reading
+ */
+ if (fxo->battery == 1 &&
+ abs_voltage > neonmwi_level &&
+ (0 == fxo->neonmwi_last_voltage ||
+ (b >= fxo->neonmwi_last_voltage - neonmwi_envelope &&
+ b <= fxo->neonmwi_last_voltage + neonmwi_envelope ))) {
+ fxo->neonmwi_last_voltage = b;
+ if (NEONMWI_ON_DEBOUNCE == fxo->neonmwi_debounce) {
+ fxo->neonmwi_offcounter = neonmwi_offlimit_cycles;
+ if(0 == fxo->neonmwi_state) {
+ zt_qevent_lock(&wc->chans[card], ZT_EVENT_NEONMWI_ACTIVE);
+ fxo->neonmwi_state = 1;
+ if (debug)
+ printk("NEON MWI active for card %d\n", card+1);
+ }
+ fxo->neonmwi_debounce++; /* terminate the processing */
+ } else if (NEONMWI_ON_DEBOUNCE > fxo->neonmwi_debounce) {
+ fxo->neonmwi_debounce++;
+ } else { /* Insure the count gets reset */
+ fxo->neonmwi_offcounter = neonmwi_offlimit_cycles;
+ }
+ } else {
+ fxo->neonmwi_debounce = 0;
+ fxo->neonmwi_last_voltage = 0;
+ }
+ /* If no neon mwi pulse for given period of time, indicte no neon mwi state */
+ if (fxo->neonmwi_state && 0 < fxo->neonmwi_offcounter ) {
+ fxo->neonmwi_offcounter--;
+ if (0 == fxo->neonmwi_offcounter) {
+ zt_qevent_lock(&wc->chans[card], ZT_EVENT_NEONMWI_INACTIVE);
+ fxo->neonmwi_state = 0;
+ if (debug)
+ printk("NEON MWI cleared for card %d\n", card+1);
+ }
+ }
+ }
#undef MS_PER_CHECK_HOOK
}
@@ -1876,7 +1954,7 @@ static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual,
reg16 |= (fxo_modes[_opermode].rt);
wctdm_setreg(wc, card, 16, reg16);
- if(fwringdetect) {
+ if(fwringdetect || neonmwi_monitor) {
/* Enable ring detector full-wave rectifier mode */
wctdm_setreg(wc, card, 18, 2);
wctdm_setreg(wc, card, 24, 0);
@@ -2599,6 +2677,9 @@ static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long dat
static int wctdm_open(struct zt_chan *chan)
{
struct wctdm *wc = chan->pvt;
+ int channo = chan->chanpos - 1;
+ unsigned long flags;
+
if (!(wc->cardflag & (1 << (chan->chanpos - 1))))
return -ENODEV;
if (wc->dead)
@@ -2608,7 +2689,14 @@ static int wctdm_open(struct zt_chan *chan)
MOD_INC_USE_COUNT;
#else
try_module_get(THIS_MODULE);
-#endif
+#endif
+ /* Reset the mwi indicators */
+ spin_lock_irqsave(&wc->reglock, flags);
+ wc->mods[channo].fxo.neonmwi_debounce = 0;
+ wc->mods[channo].fxo.neonmwi_offcounter = 0;
+ wc->mods[channo].fxo.neonmwi_state = 0;
+ spin_unlock_irqrestore(&wc->reglock, flags);
+
return 0;
}
@@ -3762,6 +3850,8 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
int y;
int ret;
+ neonmwi_offlimit_cycles = neonmwi_offlimit /MS_PER_HOOKCHECK;
+
retry:
wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL);
if (!wc) {
@@ -4012,6 +4102,10 @@ module_param(fxsrxgain, int, 0600);
module_param(ringdebounce, int, 0600);
module_param(fwringdetect, int, 0600);
module_param(latency, int, 0600);
+module_param(neonmwi_monitor, int, 0600);
+module_param(neonmwi_level, int, 0600);
+module_param(neonmwi_envelope, int, 0600);
+module_param(neonmwi_offlimit, int, 0600);
#ifdef VPM_SUPPORT
module_param(vpmsupport, int, 0600);
module_param(vpmdtmfsupport, int, 0600);
@@ -4041,6 +4135,10 @@ MODULE_PARM(fxstxgain, "i");
MODULE_PARM(fxsrxgain, "i");
MODULE_PARM(ringdebounce, "i");
MODULE_PARM(fwringdetect, "i");
+MODULE_PARM(neonmwi_monitor, "i");
+MODULE_PARM(neonmwi_level, "i");
+MODULE_PARM(neonmwi_envelope, "i");
+MODULE_PARM(neonmwi_offlimit, "i");
#ifdef VPM_SUPPORT
MODULE_PARM(vpmsupport, "i");
MODULE_PARM(vpmdtmfsupport, "i");
diff --git a/kernel/wctdm24xxp/wctdm24xxp.h b/kernel/wctdm24xxp/wctdm24xxp.h
index 79e1d30..bb2830c 100644
--- a/kernel/wctdm24xxp/wctdm24xxp.h
+++ b/kernel/wctdm24xxp/wctdm24xxp.h
@@ -220,6 +220,7 @@ struct wctdm {
struct fxo {
int wasringing;
int lastrdtx;
+ int lastrdtx_count;
int ringdebounce;
int offhook;
int battdebounce;
@@ -228,6 +229,11 @@ struct wctdm {
int lastpol;
int polarity;
int polaritydebounce;
+ int neonmwi_state;
+ int neonmwi_last_voltage;
+ unsigned int neonmwi_debounce;
+ unsigned int neonmwi_offcounter;
+
} fxo;
struct fxs {
int oldrxhook;