/****************************************************************************** * rtl8712_led.c * * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. * Linux device driver for RTL8192SU * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * Modifications for inclusion into the Linux staging tree are * Copyright(c) 2010 Larry Finger. All rights reserved. * * Contact information: * WLAN FAE <wlanfae@realtek.com> * Larry Finger <Larry.Finger@lwfinger.net> * ******************************************************************************/ #include "drv_types.h" /*=========================================================================== * Constant. *=========================================================================== * * Default LED behavior. */ #define LED_BLINK_NORMAL_INTERVAL 100 #define LED_BLINK_SLOWLY_INTERVAL 200 #define LED_BLINK_LONG_INTERVAL 400 #define LED_BLINK_NO_LINK_INTERVAL_ALPHA 1000 #define LED_BLINK_LINK_INTERVAL_ALPHA 500 #define LED_BLINK_SCAN_INTERVAL_ALPHA 180 #define LED_BLINK_FASTER_INTERVAL_ALPHA 50 #define LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA 5000 /*=========================================================================== * LED object. *=========================================================================== */ enum _LED_STATE_871x { LED_UNKNOWN = 0, LED_ON = 1, LED_OFF = 2, LED_BLINK_NORMAL = 3, LED_BLINK_SLOWLY = 4, LED_POWER_ON_BLINK = 5, LED_SCAN_BLINK = 6, /* LED is blinking during scanning period, * the # of times to blink is depend on time * for scanning. */ LED_NO_LINK_BLINK = 7, /* LED is blinking during no link state. */ LED_BLINK_StartToBlink = 8,/* Customized for Sercomm Printer * Server case */ LED_BLINK_WPS = 9, /* LED is blinkg during WPS communication */ LED_TXRX_BLINK = 10, LED_BLINK_WPS_STOP = 11, /*for ALPHA */ LED_BLINK_WPS_STOP_OVERLAP = 12, /*for BELKIN */ }; /*=========================================================================== * Prototype of protected function. *=========================================================================== */ static void BlinkTimerCallback(unsigned long data); static void BlinkWorkItemCallback(struct work_struct *work); /*=========================================================================== * LED_819xUsb routines. *=========================================================================== * * * * Description: * Initialize an LED_871x object. */ static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed, enum LED_PIN_871x LedPin) { struct net_device *nic; nic = padapter->pnetdev; pLed->padapter = padapter; pLed->LedPin = LedPin; pLed->CurrLedState = LED_OFF; pLed->bLedOn = false; pLed->bLedBlinkInProgress = false; pLed->BlinkTimes = 0; pLed->BlinkingLedState = LED_UNKNOWN; setup_timer(&pLed->BlinkTimer, BlinkTimerCallback, (unsigned long)pLed); INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback); } /* * Description: * DeInitialize an LED_871x object. */ static void DeInitLed871x(struct LED_871x *pLed) { del_timer_sync(&pLed->BlinkTimer); /* We should reset bLedBlinkInProgress if we cancel * the LedControlTimer, */ pLed->bLedBlinkInProgress = false; } /* * Description: * Turn on LED according to LedPin specified. */ static void SwLedOn(struct _adapter *padapter, struct LED_871x *pLed) { u8 LedCfg; if (padapter->bSurpriseRemoved || padapter->bDriverStopped) return; LedCfg = r8712_read8(padapter, LEDCFG); switch (pLed->LedPin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: /* SW control led0 on.*/ r8712_write8(padapter, LEDCFG, LedCfg & 0xf0); break; case LED_PIN_LED1: /* SW control led1 on.*/ r8712_write8(padapter, LEDCFG, LedCfg & 0x0f); break; default: break; } pLed->bLedOn = true; } /* * Description: * Turn off LED according to LedPin specified. */ static void SwLedOff(struct _adapter *padapter, struct LED_871x *pLed) { u8 LedCfg; if (padapter->bSurpriseRemoved || padapter->bDriverStopped) return; LedCfg = r8712_read8(padapter, LEDCFG); switch (pLed->LedPin) { case LED_PIN_GPIO0: break; case LED_PIN_LED0: LedCfg &= 0xf0; /* Set to software control.*/ r8712_write8(padapter, LEDCFG, (LedCfg | BIT(3))); break; case LED_PIN_LED1: LedCfg &= 0x0f; /* Set to software control.*/ r8712_write8(padapter, LEDCFG, (LedCfg | BIT(7))); break; default: break; } pLed->bLedOn = false; } /*=========================================================================== * Interface to manipulate LED objects. *=========================================================================== * * Description: * Initialize all LED_871x objects. */ void r8712_InitSwLeds(struct _adapter *padapter) { struct led_priv *pledpriv = &(padapter->ledpriv); pledpriv->LedControlHandler = LedControl871x; InitLed871x(padapter, &(pledpriv->SwLed0), LED_PIN_LED0); InitLed871x(padapter, &(pledpriv->SwLed1), LED_PIN_LED1); } /* Description: * DeInitialize all LED_819xUsb objects. */ void r8712_DeInitSwLeds(struct _adapter *padapter) { struct led_priv *ledpriv = &(padapter->ledpriv); DeInitLed871x(&(ledpriv->SwLed0)); DeInitLed871x(&(ledpriv->SwLed1)); } /* Description: * Implementation of LED blinking behavior. * It toggle off LED and schedule corresponding timer if necessary. */ static void SwLedBlink(struct LED_871x *pLed) { struct _adapter *padapter = pLed->padapter; struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ if (pLed->BlinkingLedState == LED_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); /* Determine if we shall change LED state again. */ pLed->BlinkTimes--; switch (pLed->CurrLedState) { case LED_BLINK_NORMAL: if (pLed->BlinkTimes == 0) bStopBlinking = true; break; case LED_BLINK_StartToBlink: if (check_fwstate(pmlmepriv, _FW_LINKED) && (pmlmepriv->fw_state & WIFI_STATION_STATE)) bStopBlinking = true; if (check_fwstate(pmlmepriv, _FW_LINKED) && ((pmlmepriv->fw_state & WIFI_ADHOC_STATE) || (pmlmepriv->fw_state & WIFI_ADHOC_MASTER_STATE))) bStopBlinking = true; else if (pLed->BlinkTimes == 0) bStopBlinking = true; break; case LED_BLINK_WPS: if (pLed->BlinkTimes == 0) bStopBlinking = true; break; default: bStopBlinking = true; break; } if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED) && !pLed->bLedOn) SwLedOn(padapter, pLed); else if (check_fwstate(pmlmepriv, _FW_LINKED) && pLed->bLedOn) SwLedOff(padapter, pLed); pLed->BlinkTimes = 0; pLed->bLedBlinkInProgress = false; } else { /* Assign LED state to toggle. */ if (pLed->BlinkingLedState == LED_ON) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; /* Schedule a timer to toggle LED state. */ switch (pLed->CurrLedState) { case LED_BLINK_NORMAL: mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; case LED_BLINK_SLOWLY: case LED_BLINK_StartToBlink: mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); break; case LED_BLINK_WPS: mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LONG_INTERVAL)); break; default: mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); break; } } } static void SwLedBlink1(struct LED_871x *pLed) { struct _adapter *padapter = pLed->padapter; struct led_priv *ledpriv = &(padapter->ledpriv); struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); struct eeprom_priv *peeprompriv = &(padapter->eeprompriv); struct LED_871x *pLed1 = &(ledpriv->SwLed1); u8 bStopBlinking = false; if (peeprompriv->CustomerID == RT_CID_819x_CAMEO) pLed = &(ledpriv->SwLed1); /* Change LED according to BlinkingLedState specified. */ if (pLed->BlinkingLedState == LED_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); if (peeprompriv->CustomerID == RT_CID_DEFAULT) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { if (!pLed1->bSWLedCtrl) { SwLedOn(padapter, pLed1); pLed1->bSWLedCtrl = true; } else if (!pLed1->bLedOn) { SwLedOn(padapter, pLed1); } } else { if (!pLed1->bSWLedCtrl) { SwLedOff(padapter, pLed1); pLed1->bSWLedCtrl = true; } else if (pLed1->bLedOn) { SwLedOff(padapter, pLed1); } } } switch (pLed->CurrLedState) { case LED_BLINK_SLOWLY: if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_BLINK_NORMAL: if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); break; case LED_SCAN_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_TXRX_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } pLed->BlinkTimes = 0; pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); break; case LED_BLINK_WPS_STOP: /* WPS success */ if (pLed->BlinkingLedState == LED_ON) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); bStopBlinking = false; } else { bStopBlinking = true; } if (bStopBlinking) { pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } pLed->bLedWPSBlinkInProgress = false; break; default: break; } } static void SwLedBlink2(struct LED_871x *pLed) { struct _adapter *padapter = pLed->padapter; struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ if (pLed->BlinkingLedState == LED_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); switch (pLed->CurrLedState) { case LED_SCAN_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; SwLedOff(padapter, pLed); } pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_TXRX_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; SwLedOff(padapter, pLed); } pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; default: break; } } static void SwLedBlink3(struct LED_871x *pLed) { struct _adapter *padapter = pLed->padapter; struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ if (pLed->BlinkingLedState == LED_ON) SwLedOn(padapter, pLed); else if (pLed->CurrLedState != LED_BLINK_WPS_STOP) SwLedOff(padapter, pLed); switch (pLed->CurrLedState) { case LED_SCAN_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; if (!pLed->bLedOn) SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; if (pLed->bLedOn) SwLedOff(padapter, pLed); } pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_TXRX_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { if (check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; if (!pLed->bLedOn) SwLedOn(padapter, pLed); } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; if (pLed->bLedOn) SwLedOff(padapter, pLed); } pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); break; case LED_BLINK_WPS_STOP: /*WPS success*/ if (pLed->BlinkingLedState == LED_ON) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); bStopBlinking = false; } else { bStopBlinking = true; } if (bStopBlinking) { pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; SwLedOn(padapter, pLed); pLed->bLedWPSBlinkInProgress = false; } break; default: break; } } static void SwLedBlink4(struct LED_871x *pLed) { struct _adapter *padapter = pLed->padapter; struct led_priv *ledpriv = &(padapter->ledpriv); struct LED_871x *pLed1 = &(ledpriv->SwLed1); u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ if (pLed->BlinkingLedState == LED_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); if (!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN) { pLed1->BlinkingLedState = LED_OFF; pLed1->CurrLedState = LED_OFF; SwLedOff(padapter, pLed1); } switch (pLed->CurrLedState) { case LED_BLINK_SLOWLY: if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_BLINK_StartToBlink: if (pLed->bLedOn) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } break; case LED_SCAN_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_TXRX_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } break; case LED_BLINK_WPS_STOP: /*WPS authentication fail*/ if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; case LED_BLINK_WPS_STOP_OVERLAP: /*WPS session overlap */ pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) { if (pLed->bLedOn) pLed->BlinkTimes = 1; else bStopBlinking = true; } if (bStopBlinking) { pLed->BlinkTimes = 10; pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } break; default: break; } } static void SwLedBlink5(struct LED_871x *pLed) { struct _adapter *padapter = pLed->padapter; u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ if (pLed->BlinkingLedState == LED_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); switch (pLed->CurrLedState) { case LED_SCAN_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; if (!pLed->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); pLed->bLedScanBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_TXRX_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; if (!pLed->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; default: break; } } static void SwLedBlink6(struct LED_871x *pLed) { struct _adapter *padapter = pLed->padapter; u8 bStopBlinking = false; /* Change LED according to BlinkingLedState specified. */ if (pLed->BlinkingLedState == LED_ON) SwLedOn(padapter, pLed); else SwLedOff(padapter, pLed); switch (pLed->CurrLedState) { case LED_TXRX_BLINK: pLed->BlinkTimes--; if (pLed->BlinkTimes == 0) bStopBlinking = true; if (bStopBlinking) { pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; if (!pLed->bLedOn) SwLedOn(padapter, pLed); pLed->bLedBlinkInProgress = false; } else { if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_BLINK_WPS: if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); break; default: break; } } /* Description: * Callback function of LED BlinkTimer, * it just schedules to corresponding BlinkWorkItem. */ static void BlinkTimerCallback(unsigned long data) { struct LED_871x *pLed = (struct LED_871x *)data; /* This fixed the crash problem on Fedora 12 when trying to do the * insmod;ifconfig up;rmmod commands. */ if (pLed->padapter->bSurpriseRemoved || pLed->padapter->bDriverStopped) return; schedule_work(&pLed->BlinkWorkItem); } /* Description: * Callback function of LED BlinkWorkItem. * We dispatch actual LED blink action according to LedStrategy. */ static void BlinkWorkItemCallback(struct work_struct *work) { struct LED_871x *pLed = container_of(work, struct LED_871x, BlinkWorkItem); struct led_priv *ledpriv = &(pLed->padapter->ledpriv); switch (ledpriv->LedStrategy) { case SW_LED_MODE0: SwLedBlink(pLed); break; case SW_LED_MODE1: SwLedBlink1(pLed); break; case SW_LED_MODE2: SwLedBlink2(pLed); break; case SW_LED_MODE3: SwLedBlink3(pLed); break; case SW_LED_MODE4: SwLedBlink4(pLed); break; case SW_LED_MODE5: SwLedBlink5(pLed); break; case SW_LED_MODE6: SwLedBlink6(pLed); break; default: SwLedBlink(pLed); break; } } /*============================================================================ * Default LED behavior. *============================================================================ * * Description: * Implement each led action for SW_LED_MODE0. * This is default strategy. */ static void SwLedControlMode1(struct _adapter *padapter, enum LED_CTL_MODE LedAction) { struct led_priv *ledpriv = &(padapter->ledpriv); struct LED_871x *pLed = &(ledpriv->SwLed0); struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); struct sitesurvey_ctrl *psitesurveyctrl = &(pmlmepriv->sitesurveyctrl); if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO) pLed = &(ledpriv->SwLed1); switch (LedAction) { case LED_CTL_START_TO_LINK: case LED_CTL_NO_LINK: if (!pLed->bLedNoLinkBlinkInProgress) { if (pLed->CurrLedState == LED_SCAN_BLINK || IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } break; case LED_CTL_LINK: if (!pLed->bLedLinkBlinkInProgress) { if (pLed->CurrLedState == LED_SCAN_BLINK || IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_NORMAL; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); } break; case LED_CTL_SITE_SURVEY: if (psitesurveyctrl->traffic_busy && check_fwstate(pmlmepriv, _FW_LINKED)) ; /* dummy branch */ else if (!pLed->bLedScanBlinkInProgress) { if (IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedScanBlinkInProgress = true; pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_CTL_TX: case LED_CTL_RX: if (!pLed->bLedBlinkInProgress) { if (pLed->CurrLedState == LED_SCAN_BLINK || IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } pLed->bLedBlinkInProgress = true; pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_START_WPS: /*wait until xinpin finish */ case LED_CTL_START_WPS_BOTTON: if (!pLed->bLedWPSBlinkInProgress) { if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_CTL_STOP_WPS: if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } if (pLed->bLedWPSBlinkInProgress) del_timer(&pLed->BlinkTimer); else pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS_STOP; if (pLed->bLedOn) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); } else { pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } break; case LED_CTL_STOP_WPS_FAIL: if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_CTL_POWER_OFF: pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; default: break; } } static void SwLedControlMode2(struct _adapter *padapter, enum LED_CTL_MODE LedAction) { struct led_priv *ledpriv = &(padapter->ledpriv); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct LED_871x *pLed = &(ledpriv->SwLed0); switch (LedAction) { case LED_CTL_SITE_SURVEY: if (pmlmepriv->sitesurveyctrl.traffic_busy) ; /* dummy branch */ else if (!pLed->bLedScanBlinkInProgress) { if (IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedScanBlinkInProgress = true; pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_CTL_TX: case LED_CTL_RX: if (!pLed->bLedBlinkInProgress && check_fwstate(pmlmepriv, _FW_LINKED)) { if (pLed->CurrLedState == LED_SCAN_BLINK || IS_LED_WPS_BLINKING(pLed)) return; pLed->bLedBlinkInProgress = true; pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_LINK: pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_START_WPS: /*wait until xinpin finish*/ case LED_CTL_START_WPS_BOTTON: if (!pLed->bLedWPSBlinkInProgress) { if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } break; case LED_CTL_STOP_WPS: pLed->bLedWPSBlinkInProgress = false; pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_STOP_WPS_FAIL: pLed->bLedWPSBlinkInProgress = false; pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_START_TO_LINK: case LED_CTL_NO_LINK: if (!IS_LED_BLINKING(pLed)) { pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } break; case LED_CTL_POWER_OFF: pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; default: break; } } static void SwLedControlMode3(struct _adapter *padapter, enum LED_CTL_MODE LedAction) { struct led_priv *ledpriv = &(padapter->ledpriv); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct LED_871x *pLed = &(ledpriv->SwLed0); switch (LedAction) { case LED_CTL_SITE_SURVEY: if (pmlmepriv->sitesurveyctrl.traffic_busy) ; /* dummy branch */ else if (!pLed->bLedScanBlinkInProgress) { if (IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedScanBlinkInProgress = true; pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_CTL_TX: case LED_CTL_RX: if (!pLed->bLedBlinkInProgress && check_fwstate(pmlmepriv, _FW_LINKED)) { if (pLed->CurrLedState == LED_SCAN_BLINK || IS_LED_WPS_BLINKING(pLed)) return; pLed->bLedBlinkInProgress = true; pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_LINK: if (IS_LED_WPS_BLINKING(pLed)) return; pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_START_WPS: /* wait until xinpin finish */ case LED_CTL_START_WPS_BOTTON: if (!pLed->bLedWPSBlinkInProgress) { if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_CTL_STOP_WPS: if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } else { pLed->bLedWPSBlinkInProgress = true; } pLed->CurrLedState = LED_BLINK_WPS_STOP; if (pLed->bLedOn) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA)); } else { pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } break; case LED_CTL_STOP_WPS_FAIL: if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_START_TO_LINK: case LED_CTL_NO_LINK: if (!IS_LED_BLINKING(pLed)) { pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } break; case LED_CTL_POWER_OFF: pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; default: break; } } static void SwLedControlMode4(struct _adapter *padapter, enum LED_CTL_MODE LedAction) { struct led_priv *ledpriv = &(padapter->ledpriv); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct LED_871x *pLed = &(ledpriv->SwLed0); struct LED_871x *pLed1 = &(ledpriv->SwLed1); switch (LedAction) { case LED_CTL_START_TO_LINK: if (pLed1->bLedWPSBlinkInProgress) { pLed1->bLedWPSBlinkInProgress = false; del_timer(&pLed1->BlinkTimer); pLed1->BlinkingLedState = LED_OFF; pLed1->CurrLedState = LED_OFF; if (pLed1->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } if (!pLed->bLedStartToLinkBlinkInProgress) { if (pLed->CurrLedState == LED_SCAN_BLINK || IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } pLed->bLedStartToLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_StartToBlink; if (pLed->bLedOn) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } } break; case LED_CTL_LINK: case LED_CTL_NO_LINK: /*LED1 settings*/ if (LedAction == LED_CTL_LINK) { if (pLed1->bLedWPSBlinkInProgress) { pLed1->bLedWPSBlinkInProgress = false; del_timer(&pLed1->BlinkTimer); pLed1->BlinkingLedState = LED_OFF; pLed1->CurrLedState = LED_OFF; if (pLed1->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } } if (!pLed->bLedNoLinkBlinkInProgress) { if (pLed->CurrLedState == LED_SCAN_BLINK || IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); } break; case LED_CTL_SITE_SURVEY: if (pmlmepriv->sitesurveyctrl.traffic_busy && check_fwstate(pmlmepriv, _FW_LINKED)) ; else if (!pLed->bLedScanBlinkInProgress) { if (IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedScanBlinkInProgress = true; pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_CTL_TX: case LED_CTL_RX: if (!pLed->bLedBlinkInProgress) { if (pLed->CurrLedState == LED_SCAN_BLINK || IS_LED_WPS_BLINKING(pLed)) return; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } pLed->bLedBlinkInProgress = true; pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_START_WPS: /*wait until xinpin finish*/ case LED_CTL_START_WPS_BOTTON: if (pLed1->bLedWPSBlinkInProgress) { pLed1->bLedWPSBlinkInProgress = false; del_timer(&pLed1->BlinkTimer); pLed1->BlinkingLedState = LED_OFF; pLed1->CurrLedState = LED_OFF; if (pLed1->bLedOn) mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); } if (!pLed->bLedWPSBlinkInProgress) { if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) { pLed->BlinkingLedState = LED_OFF; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); } else { pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); } } break; case LED_CTL_STOP_WPS: /*WPS connect success*/ if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); break; case LED_CTL_STOP_WPS_FAIL: /*WPS authentication fail*/ if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); /*LED1 settings*/ if (pLed1->bLedWPSBlinkInProgress) del_timer(&pLed1->BlinkTimer); else pLed1->bLedWPSBlinkInProgress = true; pLed1->CurrLedState = LED_BLINK_WPS_STOP; if (pLed1->bLedOn) pLed1->BlinkingLedState = LED_OFF; else pLed1->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; case LED_CTL_STOP_WPS_FAIL_OVERLAP: /*WPS session overlap*/ if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } pLed->bLedNoLinkBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_SLOWLY; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); /*LED1 settings*/ if (pLed1->bLedWPSBlinkInProgress) del_timer(&pLed1->BlinkTimer); else pLed1->bLedWPSBlinkInProgress = true; pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP; pLed1->BlinkTimes = 10; if (pLed1->bLedOn) pLed1->BlinkingLedState = LED_OFF; else pLed1->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); break; case LED_CTL_POWER_OFF: pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; if (pLed->bLedNoLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedNoLinkBlinkInProgress = false; } if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } if (pLed->bLedScanBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedScanBlinkInProgress = false; } if (pLed->bLedStartToLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedStartToLinkBlinkInProgress = false; } if (pLed1->bLedWPSBlinkInProgress) { del_timer(&pLed1->BlinkTimer); pLed1->bLedWPSBlinkInProgress = false; } pLed1->BlinkingLedState = LED_UNKNOWN; SwLedOff(padapter, pLed); SwLedOff(padapter, pLed1); break; default: break; } } static void SwLedControlMode5(struct _adapter *padapter, enum LED_CTL_MODE LedAction) { struct led_priv *ledpriv = &(padapter->ledpriv); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct LED_871x *pLed = &(ledpriv->SwLed0); if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO) pLed = &(ledpriv->SwLed1); switch (LedAction) { case LED_CTL_POWER_ON: case LED_CTL_NO_LINK: case LED_CTL_LINK: /* solid blue */ if (pLed->CurrLedState == LED_SCAN_BLINK) return; pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; pLed->bLedBlinkInProgress = false; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_SITE_SURVEY: if (pmlmepriv->sitesurveyctrl.traffic_busy && check_fwstate(pmlmepriv, _FW_LINKED)) ; /* dummy branch */ else if (!pLed->bLedScanBlinkInProgress) { if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedScanBlinkInProgress = true; pLed->CurrLedState = LED_SCAN_BLINK; pLed->BlinkTimes = 24; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_CTL_TX: case LED_CTL_RX: if (!pLed->bLedBlinkInProgress) { if (pLed->CurrLedState == LED_SCAN_BLINK) return; pLed->bLedBlinkInProgress = true; pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_POWER_OFF: pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } SwLedOff(padapter, pLed); break; default: break; } } static void SwLedControlMode6(struct _adapter *padapter, enum LED_CTL_MODE LedAction) { struct led_priv *ledpriv = &(padapter->ledpriv); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct LED_871x *pLed = &(ledpriv->SwLed0); switch (LedAction) { case LED_CTL_POWER_ON: case LED_CTL_NO_LINK: case LED_CTL_LINK: /*solid blue*/ case LED_CTL_SITE_SURVEY: if (IS_LED_WPS_BLINKING(pLed)) return; pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; pLed->bLedBlinkInProgress = false; mod_timer(&(pLed->BlinkTimer), jiffies + msecs_to_jiffies(0)); break; case LED_CTL_TX: case LED_CTL_RX: if (!pLed->bLedBlinkInProgress && check_fwstate(pmlmepriv, _FW_LINKED)) { if (IS_LED_WPS_BLINKING(pLed)) return; pLed->bLedBlinkInProgress = true; pLed->CurrLedState = LED_TXRX_BLINK; pLed->BlinkTimes = 2; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); } break; case LED_CTL_START_WPS: /*wait until xinpin finish*/ case LED_CTL_START_WPS_BOTTON: if (!pLed->bLedWPSBlinkInProgress) { if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } pLed->bLedWPSBlinkInProgress = true; pLed->CurrLedState = LED_BLINK_WPS; if (pLed->bLedOn) pLed->BlinkingLedState = LED_OFF; else pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); } break; case LED_CTL_STOP_WPS_FAIL: case LED_CTL_STOP_WPS: if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } pLed->CurrLedState = LED_ON; pLed->BlinkingLedState = LED_ON; mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); break; case LED_CTL_POWER_OFF: pLed->CurrLedState = LED_OFF; pLed->BlinkingLedState = LED_OFF; if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedBlinkInProgress = false; } if (pLed->bLedWPSBlinkInProgress) { del_timer(&pLed->BlinkTimer); pLed->bLedWPSBlinkInProgress = false; } SwLedOff(padapter, pLed); break; default: break; } } /* Description: * Dispatch LED action according to pHalData->LedStrategy. */ void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction) { struct led_priv *ledpriv = &(padapter->ledpriv); if (!ledpriv->bRegUseLed) return; switch (ledpriv->LedStrategy) { case SW_LED_MODE0: break; case SW_LED_MODE1: SwLedControlMode1(padapter, LedAction); break; case SW_LED_MODE2: SwLedControlMode2(padapter, LedAction); break; case SW_LED_MODE3: SwLedControlMode3(padapter, LedAction); break; case SW_LED_MODE4: SwLedControlMode4(padapter, LedAction); break; case SW_LED_MODE5: SwLedControlMode5(padapter, LedAction); break; case SW_LED_MODE6: SwLedControlMode6(padapter, LedAction); break; default: break; } }