diff options
author | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2006-08-10 03:12:25 +0000 |
---|---|---|
committer | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2006-08-10 03:12:25 +0000 |
commit | 7d33e1eca2cc193bd0127816c7d487e3ef73e5bb (patch) | |
tree | 69d148d2587518cd5e04f173a593eb7a0c497203 /xpp/card_fxo.c | |
parent | 4ab762499c932cb80394ec1ec6b93879004a5214 (diff) |
* New SOFT_RING detection in FXO:
- Poll register 0x05 on each DAA
- When enough energy (value of 0x20|0x40 occurs enough times), raise
the ringing[] flag.
- When the value show no energy, lower the ringing[] flag.
- When we get SIG_CHANGED of stop ringing -- stop polling.
* More debugging messages for proc files
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1285 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'xpp/card_fxo.c')
-rw-r--r-- | xpp/card_fxo.c | 97 |
1 files changed, 83 insertions, 14 deletions
diff --git a/xpp/card_fxo.c b/xpp/card_fxo.c index 2627e21..89bec14 100644 --- a/xpp/card_fxo.c +++ b/xpp/card_fxo.c @@ -70,6 +70,12 @@ static int process_slic_cmdline(xpd_t *xpd, char *cmdline); #define PROC_DAA_FNAME "slics" #define PROC_FXO_INFO_FNAME "fxo_info" +#ifdef SOFT_RING +#define POLL_RING_INTERVAL 1 +#define RING_THRESHOLD 5 +#define DAA_RING_REGISTER 0x05 +#endif + struct FXO_priv_data { struct proc_dir_entry *xpd_slic; struct proc_dir_entry *fxo_info; @@ -79,6 +85,9 @@ struct FXO_priv_data { xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */ int blinking[NUM_LEDS][CHANNELS_PERXPD]; +#ifdef SOFT_RING + ushort ring_thresh[CHANNELS_PERXPD]; +#endif }; /*---------------- FXO: Static functions ----------------------------------*/ @@ -174,6 +183,24 @@ static void handle_fxo_leds(xpd_t *xpd) spin_unlock_irqrestore(&xpd->lock, flags); } +static void mark_ring(xpd_t *xpd, lineno_t pos, bool on) +{ + struct FXO_priv_data *priv; + + priv = xpd->priv; + BUG_ON(!priv); + if(on && !xpd->ringing[pos]) { + DBG("%s/%s/%d: START\n", xpd->xbus->busname, xpd->xpdname, pos); + xpd->ringing[pos] = 1; + MARK_BLINK(priv, pos, LED_GREEN, LED_BLINK); + } else if(!on && xpd->ringing[pos]) { + DBG("%s/%s/%d: STOP\n", xpd->xbus->busname, xpd->xpdname, pos); + xpd->ringing[pos] = 0; + if(IS_BLINKING(priv, pos, LED_GREEN)) + MARK_BLINK(priv, pos, LED_GREEN, 0); + } +} + static void do_sethook(xpd_t *xpd, int pos, bool offhook) { unsigned long flags; @@ -187,7 +214,7 @@ static void do_sethook(xpd_t *xpd, int pos, bool offhook) DBG("%s/%s/%d: WARNING: called while battery is off\n", xpd->xbus->busname, xpd->xpdname, pos); } spin_lock_irqsave(&xpd->lock, flags); - xpd->ringing[pos] = 0; // No more rings + mark_ring(xpd, pos, 0); // No more rings CALL_XMETHOD(SETHOOK, xpd->xbus, xpd, pos, offhook); if(offhook) { BIT_SET(xpd->hookstate, pos); @@ -413,6 +440,21 @@ static void poll_battery(xbus_t *xbus, xpd_t *xpd) } } +#ifdef SOFT_RING + +static void poll_ring(xbus_t *xbus, xpd_t *xpd) +{ + int i; + struct FXO_priv_data *priv; + + priv = xpd->priv; + BUG_ON(!priv); + for_each_line(xpd, i) { + if(priv->ring_thresh[i] > 0) + CALL_PROTO(FXO, DAA_QUERY, xbus, xpd, i, DAA_RING_REGISTER); + } +} +#endif static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd) { @@ -426,6 +468,10 @@ static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd) if(poll_battery_interval != 0 && (rate_limit % poll_battery_interval) == 0) { poll_battery(xbus, xpd); } +#ifdef SOFT_RING + if((rate_limit % POLL_RING_INTERVAL) == 0) + poll_ring(xbus, xpd); +#endif handle_fxo_leds(xpd); return 0; } @@ -552,7 +598,6 @@ static /* 0x0F */ HOSTCMD(FXO, SETHOOK, int pos, bool offhook) xpacket_t *pack; slic_cmd_t *sc; int len; - unsigned long flags; bool value; BUG_ON(!xbus); @@ -560,7 +605,6 @@ static /* 0x0F */ HOSTCMD(FXO, SETHOOK, int pos, bool offhook) value = (offhook) ? 0x09 : 0x08; // value |= BIT(3); /* Bit 3 is for CID */ DBG("%s/%s/%d: SETHOOK: value=0x%02X %s\n", xbus->busname, xpd->xpdname, pos, value, (offhook)?"OFFHOOK":"ONHOOK"); - spin_lock_irqsave(&xpd->lock, flags); MARK_LED(xpd, pos, LED_GREEN, (offhook)?LED_ON:LED_OFF); XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id); sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd); @@ -568,8 +612,7 @@ static /* 0x0F */ HOSTCMD(FXO, SETHOOK, int pos, bool offhook) pack->datalen = len; packet_send(xbus, pack); if(!offhook) - xpd->ringing[pos] = 0; - spin_unlock_irqrestore(&xpd->lock, flags); + mark_ring(xpd, pos, 0); // No more rings return ret; } @@ -619,17 +662,18 @@ HANDLER_DEF(FXO, SIG_CHANGED) spin_lock_irqsave(&xpd->lock, flags); for_each_line(xpd, i) { if(IS_SET(sig_toggles, i)) { - struct zt_chan *chan = &xpd->span.chans[i]; - if(IS_SET(sig_status, i)) { - DBG("%s/%s/%d: RING-ON\n", xbus->busname, xpd->xpdname, chan->channo); - xpd->ringing[i] = 1; - MARK_BLINK(priv, i, LED_GREEN, LED_BLINK); +#ifdef SOFT_RING + priv->ring_thresh[i]++; /* trigger register polling */ +#else + mark_ring(xpd, i, 1); +#endif } else { - DBG("%s/%s/%d: RING-OFF\n", xbus->busname, xpd->xpdname, chan->channo); - xpd->ringing[i] = 0; - if(IS_BLINKING(priv, i, LED_GREEN)) - MARK_BLINK(priv, i, LED_GREEN, 0); +#ifdef SOFT_RING + priv->ring_thresh[i] = 0; +#else + mark_ring(xpd, i, 0); +#endif } } } @@ -671,6 +715,24 @@ HANDLER_DEF(FXO, DAA_REPLY) } } } +#ifdef SOFT_RING + if(!info->indirect && info->reg_num == DAA_RING_REGISTER) { + bool ringit = (info->data_low & (0x20 | 0x40)) ? 1 : 0; /* Ring positive | Ring negative */ + int i; + + for_each_line(xpd, i) { + if(IS_SET(lines, i)) { + if(ringit) { + if(priv->ring_thresh[i]++ > RING_THRESHOLD) { + mark_ring(xpd, i, 1); + } + } else { + mark_ring(xpd, i, 0); + } + } + } + } +#endif #if 0 DBG("DAA_REPLY: xpd #%d %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n", xpd->id, (info->indirect)?"I":"D", @@ -772,6 +834,13 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count, in if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) len += sprintf(page + len, "%d ", IS_BLINKING(priv,i,LED_GREEN)); } +#ifdef SOFT_RING + len += sprintf(page + len, "\n\t%-17s: ", "ring_thresh"); + for_each_line(xpd, i) { + if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) + len += sprintf(page + len, "%d ", priv->ring_thresh[i]); + } +#endif len += sprintf(page + len, "\n\t%-17s: ", "battery"); for_each_line(xpd, i) { len += sprintf(page + len, "%d ", IS_SET(priv->battery, i)); |