summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-03-19 23:33:52 -0500
committerShaun Ruffell <sruffell@digium.com>2011-04-15 14:19:03 -0500
commit5e850c02b8a4410d607ae23d78a121100406997b (patch)
treecb3ccd7c32170652710c6c4c1590e2ca9203ea82
parent37936432c02c1e9dd2f6c08a894ac2a4eaf9bcff (diff)
wctdm24xxp: Use time interval for debouncing ring detect.
We do not necessarily want to assume that the ring dection function is called for every frame. Also, use a state machine for ring detection. Signed-off-by: Shaun Ruffell <sruffell@digium.com>
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c211
-rw-r--r--drivers/dahdi/wctdm24xxp/wctdm24xxp.h23
2 files changed, 147 insertions, 87 deletions
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index b65f868..3535ed5 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -163,6 +163,8 @@ static alpha indirect_regs[] =
{43,66,"LOOP_CLOSE_TRES_LOW",0x1000},
};
+#define DEBUG
+
/* names of HWEC modules */
static const char *vpmadt032_name = "VPMADT032";
static const char *noec_name = "NONE";
@@ -1730,101 +1732,150 @@ static void wctdm_qrvdri_check_hook(struct wctdm *wc, int card)
return;
}
+static inline bool is_fxo_ringing(const struct fxo *const fxo)
+{
+ return ((fxo->hook_ring_shadow & 0x60) &&
+ (fxo->battery_state == BATTERY_PRESENT));
+}
+
+static inline bool is_fxo_ringing_positive(const struct fxo *const fxo)
+{
+ return (((fxo->hook_ring_shadow & 0x60) == 0x20) &&
+ (fxo->battery_state == BATTERY_PRESENT));
+}
+
+static inline bool is_fxo_ringing_negative(const struct fxo *const fxo)
+{
+ return (((fxo->hook_ring_shadow & 0x60) == 0x40) &&
+ (fxo->battery_state == BATTERY_PRESENT));
+}
+
+#ifdef DEBUG
+static inline void set_ring(struct fxo *fxo, enum ring_detector_state new)
+{
+ union modtypes *modtypes = container_of(fxo, union modtypes, fxo);
+ fxo->ring_state = new;
+}
+#else
+static inline void set_ring(struct fxo *fxo, enum ring_detector_state new)
+{
+ fxo->ring_state = new;
+}
+#endif
+
+static void wctdm_fxo_ring_detect(struct wctdm *wc, struct wctdm_module *mod)
+{
+ struct fxo *const fxo = &mod->mod.fxo;
+
+ /* 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 giving 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 traversals) */
+
+ switch (fxo->ring_state) {
+ case DEBOUNCING_RINGING_POSITIVE:
+ if (is_fxo_ringing_negative(fxo)) {
+ if (++fxo->ring_polarity_change_count > 4) {
+ dahdi_hooksig(&mod->chan->chan,
+ DAHDI_RXSIG_RING);
+ set_ring(fxo, RINGING);
+ if (debug) {
+ dev_info(&wc->vb.pdev->dev,
+ "RING on %s!\n",
+ mod->chan->chan.name);
+ }
+ } else {
+ set_ring(fxo, DEBOUNCING_RINGING_NEGATIVE);
+ }
+
+ } else if (time_after(wc->framecount,
+ fxo->ringdebounce_timer)) {
+ set_ring(fxo, RINGOFF);
+ }
+ break;
+ case DEBOUNCING_RINGING_NEGATIVE:
+ if (is_fxo_ringing_positive(fxo)) {
+ if (++fxo->ring_polarity_change_count > 4) {
+ dahdi_hooksig(&mod->chan->chan,
+ DAHDI_RXSIG_RING);
+ set_ring(fxo, RINGING);
+ if (debug) {
+ dev_info(&wc->vb.pdev->dev,
+ "RING on %s!\n",
+ mod->chan->chan.name);
+ }
+ } else {
+ set_ring(fxo, DEBOUNCING_RINGING_POSITIVE);
+ }
+
+ } else if (time_after(wc->framecount,
+ fxo->ringdebounce_timer)) {
+ set_ring(fxo, RINGOFF);
+ }
+ break;
+ case RINGING:
+ if (!is_fxo_ringing(fxo)) {
+ set_ring(fxo, DEBOUNCING_RINGOFF);
+ fxo->ringdebounce_timer =
+ wc->framecount + ringdebounce / 2;
+ }
+ break;
+ case DEBOUNCING_RINGOFF:
+ if (!is_fxo_ringing(fxo)) {
+ if (time_after(wc->framecount,
+ fxo->ringdebounce_timer)) {
+ if (debug) {
+ dev_info(&wc->vb.pdev->dev,
+ "NO RING on %s!\n",
+ mod->chan->chan.name);
+ }
+ dahdi_hooksig(&mod->chan->chan,
+ DAHDI_RXSIG_OFFHOOK);
+ set_ring(fxo, RINGOFF);
+ }
+ } else {
+ set_ring(fxo, RINGING);
+ }
+ break;
+ case RINGOFF:
+ if (is_fxo_ringing(fxo)) {
+ /* Look for positive/negative crossings in ring status
+ * reg */
+ if (is_fxo_ringing_positive(fxo))
+ set_ring(fxo, DEBOUNCING_RINGING_POSITIVE);
+ else
+ set_ring(fxo, DEBOUNCING_RINGING_NEGATIVE);
+ fxo->ringdebounce_timer =
+ wc->framecount + ringdebounce / 8;
+ fxo->ring_polarity_change_count = 0;
+ }
+ break;
+ }
+}
+
static void
wctdm_voicedaa_check_hook(struct wctdm *wc, struct wctdm_module *const mod)
{
#define MS_PER_CHECK_HOOK 1
- unsigned char res;
signed char b;
unsigned int abs_voltage;
struct fxo *const fxo = &mod->mod.fxo;
/* Try to track issues that plague slot one FXO's */
- b = fxo->hook_ring_shadow;
- b &= 0x9b;
+ b = fxo->hook_ring_shadow & 0x9b;
+
if (fxo->offhook) {
if (b != 0x9)
wctdm_setreg_intr(wc, mod, 5, 0x9);
} else {
if (b != 0x8)
wctdm_setreg_intr(wc, mod, 5, 0x8);
- }
- if (!fxo->offhook) {
- 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 = fxo->hook_ring_shadow & 0x60;
- if (0 == 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)
- dev_info(&wc->vb.pdev->dev, "FW RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
- dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_RING);
- fxo->ringdebounce = ringdebounce / 16;
- } else {
- fxo->lastrdtx = res;
- fxo->ringdebounce = ringdebounce / 16;
- }
- /* 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)
- dev_info(&wc->vb.pdev->dev, "FW NO RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
- dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_OFFHOOK);
- }
- }
- } else {
- res = fxo->hook_ring_shadow;
- if ((res & 0x60) && (fxo->battery == BATTERY_PRESENT)) {
- fxo->ringdebounce += (DAHDI_CHUNKSIZE * 16);
- if (fxo->ringdebounce >= DAHDI_CHUNKSIZE * ringdebounce) {
- if (!fxo->wasringing) {
- fxo->wasringing = 1;
- dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_RING);
- if (debug)
- dev_info(&wc->vb.pdev->dev, "RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
- }
- fxo->ringdebounce = DAHDI_CHUNKSIZE * ringdebounce;
- }
- } else {
- fxo->ringdebounce -= DAHDI_CHUNKSIZE * 4;
- if (fxo->ringdebounce <= 0) {
- if (fxo->wasringing) {
- fxo->wasringing = 0;
- dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_OFFHOOK);
- if (debug)
- dev_info(&wc->vb.pdev->dev, "NO RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
- }
- fxo->ringdebounce = 0;
- }
-
- }
- }
+
+ wctdm_fxo_ring_detect(wc, mod);
}
b = fxo->line_voltage_status;
@@ -2111,7 +2162,7 @@ static void wctdm_fxs_off_hook(struct wctdm *wc, struct wctdm_module *const mod)
#ifdef DEBUG
if (robust)
- wctdm_init_proslic(wc, card, 1, 0, 1);
+ wctdm_init_proslic(wc, mod, 1, 0, 1);
#endif
}
diff --git a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
index 2ce703c..47e72af 100644
--- a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
+++ b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
@@ -116,6 +116,15 @@ enum hook_state {
DEBOUNCING_OFF_HOOK,
};
+enum ring_detector_state {
+ RINGOFF = 0,
+ DEBOUNCING_RINGING_POSITIVE,
+ DEBOUNCING_RINGING_NEGATIVE,
+ DEBOUNCING_RINGING_OFF,
+ RINGING,
+ DEBOUNCING_RINGOFF,
+};
+
struct wctdm_cmd {
struct list_head node;
struct completion *complete;
@@ -150,10 +159,11 @@ struct wctdm_chan {
};
struct fxo {
- int wasringing;
- int lastrdtx;
- int lastrdtx_count;
- int ringdebounce;
+ enum ring_detector_state ring_state:4;
+ enum battery_state battery_state:4;
+ u8 ring_polarity_change_count:4;
+ u8 hook_ring_shadow;
+ s8 line_voltage_status;
int offhook;
int battdebounce;
int battalarm;
@@ -166,8 +176,7 @@ struct fxo {
unsigned int neonmwi_debounce;
unsigned int neonmwi_offcounter;
unsigned long display_fxovoltage;
- u8 hook_ring_shadow;
- s8 line_voltage_status;
+ unsigned long ringdebounce_timer;
};
struct fxs {
@@ -226,7 +235,7 @@ enum module_type {
};
struct wctdm_module {
- union {
+ union modtypes {
struct fxo fxo;
struct fxs fxs;
struct qrv qrv;