diff options
Diffstat (limited to 'drivers/staging/rtl8712/rtl8712_led.c')
-rw-r--r-- | drivers/staging/rtl8712/rtl8712_led.c | 1830 |
1 files changed, 1830 insertions, 0 deletions
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c new file mode 100644 index 0000000000..d5fc9026b0 --- /dev/null +++ b/drivers/staging/rtl8712/rtl8712_led.c @@ -0,0 +1,1830 @@ +// SPDX-License-Identifier: GPL-2.0 +/****************************************************************************** + * rtl8712_led.c + * + * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. + * Linux device driver for RTL8192SU + * + * 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_SUCCESS_INTERVAL_ALPHA 5000 + +/*=========================================================================== + * LED object. + *=========================================================================== + */ +enum _LED_STATE_871x { + LED_UNKNOWN = 0, + LED_STATE_ON = 1, + LED_STATE_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(struct timer_list *t); + +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) +{ + pLed->padapter = padapter; + pLed->LedPin = LedPin; + pLed->CurrLedState = LED_STATE_OFF; + pLed->bLedOn = false; + pLed->bLedBlinkInProgress = false; + pLed->BlinkTimes = 0; + pLed->BlinkingLedState = LED_UNKNOWN; + timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0); + 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->surprise_removed || padapter->driver_stopped) + 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->surprise_removed || padapter->driver_stopped) + 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_STATE_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_STATE_ON) + pLed->BlinkingLedState = LED_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_ON) { + pLed->BlinkingLedState = LED_STATE_OFF; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); + bStopBlinking = false; + } else { + bStopBlinking = true; + } + if (bStopBlinking) { + pLed->bLedLinkBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_NORMAL; + if (pLed->bLedOn) + pLed->BlinkingLedState = LED_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; + SwLedOn(padapter, pLed); + } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; + SwLedOff(padapter, pLed); + } + pLed->bLedScanBlinkInProgress = false; + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = LED_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; + SwLedOn(padapter, pLed); + } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; + SwLedOff(padapter, pLed); + } + pLed->bLedBlinkInProgress = false; + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = LED_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; + if (!pLed->bLedOn) + SwLedOn(padapter, pLed); + } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; + if (pLed->bLedOn) + SwLedOff(padapter, pLed); + } + pLed->bLedScanBlinkInProgress = false; + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = LED_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; + if (!pLed->bLedOn) + SwLedOn(padapter, pLed); + } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; + if (pLed->bLedOn) + SwLedOff(padapter, pLed); + } + pLed->bLedBlinkInProgress = false; + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = LED_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_ON) { + pLed->BlinkingLedState = LED_STATE_OFF; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); + bStopBlinking = false; + } else { + bStopBlinking = true; + } + if (bStopBlinking) { + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_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_STATE_ON) + SwLedOn(padapter, pLed); + else + SwLedOff(padapter, pLed); + if (!pLed1->bLedWPSBlinkInProgress && + pLed1->BlinkingLedState == LED_UNKNOWN) { + pLed1->BlinkingLedState = LED_STATE_OFF; + pLed1->CurrLedState = LED_STATE_OFF; + SwLedOff(padapter, pLed1); + } + switch (pLed->CurrLedState) { + case LED_BLINK_SLOWLY: + if (pLed->bLedOn) + pLed->BlinkingLedState = LED_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); + } else { + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); + } else { + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_ON; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = LED_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; + if (!pLed->bLedOn) + SwLedOn(padapter, pLed); + pLed->bLedBlinkInProgress = false; + } else { + if (pLed->bLedOn) + pLed->BlinkingLedState = LED_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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(struct timer_list *t) +{ + struct LED_871x *pLed = from_timer(pLed, t, BlinkTimer); + + /* This fixed the crash problem on Fedora 12 when trying to do the + * insmod;ifconfig up;rmmod commands. + */ + if (pLed->padapter->surprise_removed || pLed->padapter->driver_stopped) + 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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); + } else { + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_ON; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); + break; + case LED_CTL_POWER_OFF: + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_ON; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); + } + break; + + case LED_CTL_LINK: + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; + mod_timer(&pLed->BlinkTimer, + jiffies + msecs_to_jiffies(0)); + } + break; + + case LED_CTL_STOP_WPS: + pLed->bLedWPSBlinkInProgress = false; + pLed->CurrLedState = LED_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; + mod_timer(&pLed->BlinkTimer, + jiffies + msecs_to_jiffies(0)); + break; + + case LED_CTL_STOP_WPS_FAIL: + pLed->bLedWPSBlinkInProgress = false; + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; + mod_timer(&pLed->BlinkTimer, + jiffies + msecs_to_jiffies(0)); + } + break; + case LED_CTL_POWER_OFF: + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); + } else { + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_OFF; + mod_timer(&pLed->BlinkTimer, + jiffies + msecs_to_jiffies(0)); + } + break; + case LED_CTL_POWER_OFF: + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + pLed1->CurrLedState = LED_STATE_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_STATE_OFF; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); + } else { + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + pLed1->CurrLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + pLed1->CurrLedState = LED_STATE_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_STATE_OFF; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); + } else { + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed1->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed1->BlinkingLedState = LED_STATE_ON; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); + break; + case LED_CTL_POWER_OFF: + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_ON; + mod_timer(&pLed->BlinkTimer, jiffies + + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); + } + break; + case LED_CTL_POWER_OFF: + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_OFF; + else + pLed->BlinkingLedState = LED_STATE_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_STATE_ON; + pLed->BlinkingLedState = LED_STATE_ON; + mod_timer(&pLed->BlinkTimer, + jiffies + msecs_to_jiffies(0)); + break; + case LED_CTL_POWER_OFF: + pLed->CurrLedState = LED_STATE_OFF; + pLed->BlinkingLedState = LED_STATE_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; + } +} + +void r8712_flush_led_works(struct _adapter *padapter) +{ + struct led_priv *pledpriv = &padapter->ledpriv; + + flush_work(&pledpriv->SwLed0.BlinkWorkItem); + flush_work(&pledpriv->SwLed1.BlinkWorkItem); +} |