From 6a04e6704a129a6efc6dcad0c8a513d2fafea579 Mon Sep 17 00:00:00 2001 From: tzafrir Date: Thu, 10 Aug 2006 02:40:45 +0000 Subject: Better LED handling for fxo (copied from fxs): - Fix both branches/RELEASE-1.1.0 and trunk/ - Use a ledcontrol bitmask to mark led on/off - Actuall led commands are send only from handle_fxo_leds() git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1280 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- xpp/card_fxo.c | 60 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 22 deletions(-) (limited to 'xpp') diff --git a/xpp/card_fxo.c b/xpp/card_fxo.c index ae7c06f..2627e21 100644 --- a/xpp/card_fxo.c +++ b/xpp/card_fxo.c @@ -77,13 +77,24 @@ struct FXO_priv_data { slic_reply_t last_reply; xpp_line_t battery; 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]; }; /*---------------- FXO: Static functions ----------------------------------*/ #define IS_BLINKING(priv,pos,color) ((priv)->blinking[color][pos] != 0) -#define DO_BLINK(priv,pos,color,val) ((priv)->blinking[color][pos] = (val)) +#define MARK_BLINK(priv,pos,color,val) ((priv)->blinking[color][pos] = (val)) + +void MARK_LED(xpd_t *xpd, lineno_t pos, byte color, bool on) +{ + struct FXO_priv_data *priv = xpd->priv; + + if(on) + BIT_SET(priv->ledcontrol[color], pos); + else + BIT_CLR(priv->ledcontrol[color], pos); +} /* * LED control is done via DAA register 0x20 @@ -130,10 +141,10 @@ out: static void handle_fxo_leds(xpd_t *xpd) { - int i; - unsigned long flags; + int i; + unsigned long flags; const enum fxo_leds color = LED_GREEN; - unsigned int timer_count; + unsigned int timer_count; struct FXO_priv_data *priv; BUG_ON(!xpd); @@ -146,7 +157,7 @@ static void handle_fxo_leds(xpd_t *xpd) if(IS_BLINKING(priv,i,color)) { // led state is toggled if((timer_count % LED_BLINK_PERIOD) == 0) { - DBG("%s/%s/%d: led_state=%s\n", xpd->xbus->busname, xpd->xpdname, i, + DBG("%s/%s/%d: ledstate=%s\n", xpd->xbus->busname, xpd->xpdname, i, (IS_SET(priv->ledstate[color], i))?"ON":"OFF"); if(!IS_SET(priv->ledstate[color], i)) { do_led(xpd, i, color, 1); @@ -154,6 +165,10 @@ static void handle_fxo_leds(xpd_t *xpd) do_led(xpd, i, color, 0); } } + } else if(IS_SET(priv->ledcontrol[color], i) && !IS_SET(priv->ledstate[color], i)) { + do_led(xpd, i, color, 1); + } else if(!IS_SET(priv->ledcontrol[color], i) && IS_SET(priv->ledstate[color], i)) { + do_led(xpd, i, color, 0); } } spin_unlock_irqrestore(&xpd->lock, flags); @@ -282,7 +297,6 @@ static int FXO_card_zaptel_preregistration(xpd_t *xpd, bool on) xbus_t *xbus; struct FXO_priv_data *priv; int i; - unsigned long flags; BUG_ON(!xpd); xbus = xpd->xbus; @@ -300,11 +314,9 @@ static int FXO_card_zaptel_preregistration(xpd_t *xpd, bool on) cur_chan->pvt = xpd; cur_chan->sigcap = FXO_DEFAULT_SIGCAP; } - spin_lock_irqsave(&xpd->lock, flags); - do_led(xpd, ALL_LINES, LED_GREEN, LED_OFF); - spin_unlock_irqrestore(&xpd->lock, flags); + MARK_LED(xpd, ALL_LINES, LED_GREEN, LED_OFF); for_each_line(xpd, i) { - do_led(xpd, i, LED_GREEN, LED_ON); + MARK_LED(xpd, i, LED_GREEN, LED_ON); mdelay(50); } return 0; @@ -323,7 +335,7 @@ static int FXO_card_zaptel_postregistration(xpd_t *xpd, bool on) BUG_ON(!priv); DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on); for_each_line(xpd, i) { - do_led(xpd, i, LED_GREEN, LED_OFF); + MARK_LED(xpd, i, LED_GREEN, LED_OFF); mdelay(50); } return 0; @@ -433,7 +445,7 @@ static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a int i,ret; BUG_ON(!xpd); - DBG("cmd: 0x%x, expecting: 0x%lx, pos=%d.\n", cmd, WCTDM_SET_ECHOTUNE, pos); + DBG("cmd: 0x%X, expecting: 0x%X, pos=%d.\n", cmd, WCTDM_SET_ECHOTUNE, pos); switch (cmd) { case WCTDM_SET_ECHOTUNE: DBG("-- Setting echo registers: \n"); @@ -474,7 +486,6 @@ static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a static /* 0x0F */ HOSTCMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on) { - unsigned long flags; int ret = 0; int i; @@ -486,15 +497,11 @@ static /* 0x0F */ HOSTCMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on) DBG("Channel Activation: 0x%4X %s\n", lines, (on) ? "on" : "off"); if(on) { for_each_line(xpd, i) { - spin_lock_irqsave(&xpd->lock, flags); - do_led(xpd, i, LED_GREEN, LED_ON); - spin_unlock_irqrestore(&xpd->lock, flags); + MARK_LED(xpd, i, LED_GREEN, LED_ON); mdelay(20); } for_each_line(xpd, i) { - spin_lock_irqsave(&xpd->lock, flags); - do_led(xpd, i, LED_GREEN, LED_OFF); - spin_unlock_irqrestore(&xpd->lock, flags); + MARK_LED(xpd, i, LED_GREEN, LED_OFF); mdelay(20); } } @@ -554,12 +561,12 @@ static /* 0x0F */ HOSTCMD(FXO, SETHOOK, int pos, bool offhook) // 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); len = slic_cmd_direct_write(sc, BIT(pos), 0x05, value); pack->datalen = len; packet_send(xbus, pack); - do_led(xpd, pos, LED_GREEN, (offhook)?LED_ON:LED_OFF); if(!offhook) xpd->ringing[pos] = 0; spin_unlock_irqrestore(&xpd->lock, flags); @@ -599,12 +606,15 @@ HANDLER_DEF(FXO, SIG_CHANGED) xpp_line_t sig_toggles = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_toggles); unsigned long flags; int i; + struct FXO_priv_data *priv; if(!xpd) { NOTICE("%s: received %s for non-existing xpd: %d\n", __FUNCTION__, cmd->name, XPD_NUM(pack->content.addr)); return -EPROTO; } + priv = xpd->priv; + BUG_ON(!priv); DBG("%s/%s: (PSTN) sig_toggles=0x%04X sig_status=0x%04X\n", xpd->xbus->busname, xpd->xpdname, sig_toggles, sig_status); spin_lock_irqsave(&xpd->lock, flags); for_each_line(xpd, i) { @@ -614,11 +624,12 @@ HANDLER_DEF(FXO, SIG_CHANGED) if(IS_SET(sig_status, i)) { DBG("%s/%s/%d: RING-ON\n", xbus->busname, xpd->xpdname, chan->channo); xpd->ringing[i] = 1; - do_led(xpd, i, LED_GREEN, LED_ON); + MARK_BLINK(priv, i, LED_GREEN, LED_BLINK); } else { DBG("%s/%s/%d: RING-OFF\n", xbus->busname, xpd->xpdname, chan->channo); xpd->ringing[i] = 0; - do_led(xpd, i, LED_GREEN, LED_OFF); + if(IS_BLINKING(priv, i, LED_GREEN)) + MARK_BLINK(priv, i, LED_GREEN, 0); } } } @@ -751,6 +762,11 @@ 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_SET(priv->ledstate[LED_GREEN], i)); } + len += sprintf(page + len, "\n\t%-17s: ", "ledcontrol"); + for_each_line(xpd, i) { + if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) + len += sprintf(page + len, "%d ", IS_SET(priv->ledcontrol[LED_GREEN], i)); + } len += sprintf(page + len, "\n\t%-17s: ", "blinking"); for_each_line(xpd, i) { if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) -- cgit v1.2.3