summaryrefslogtreecommitdiff
path: root/xpp/card_fxo.c
diff options
context:
space:
mode:
authortzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-08-10 03:12:25 +0000
committertzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-08-10 03:12:25 +0000
commit7d33e1eca2cc193bd0127816c7d487e3ef73e5bb (patch)
tree69d148d2587518cd5e04f173a593eb7a0c497203 /xpp/card_fxo.c
parent4ab762499c932cb80394ec1ec6b93879004a5214 (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.c97
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));