linux/drivers/staging/rtl8188eu/core/rtw_led.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 *
  15 ******************************************************************************/
  16
  17#include <drv_types.h>
  18#include "rtw_led.h"
  19
  20/*  */
  21/*      Description: */
  22/*              Callback function of LED BlinkTimer, */
  23/*              it just schedules to corresponding BlinkWorkItem/led_blink_hdl */
  24/*  */
  25void BlinkTimerCallback(unsigned long data)
  26{
  27        struct LED_871x *pLed = (struct LED_871x *)data;
  28        struct adapter *padapter = pLed->padapter;
  29
  30        if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
  31                return;
  32
  33        schedule_work(&(pLed->BlinkWorkItem));
  34}
  35
  36/*  */
  37/*      Description: */
  38/*              Callback function of LED BlinkWorkItem. */
  39/*  */
  40void BlinkWorkItemCallback(struct work_struct *work)
  41{
  42        struct LED_871x *pLed = container_of(work, struct LED_871x, BlinkWorkItem);
  43        BlinkHandler(pLed);
  44}
  45
  46/*  */
  47/*      Description: */
  48/*              Reset status of LED_871x object. */
  49/*  */
  50void ResetLedStatus(struct LED_871x *pLed)
  51{
  52        pLed->CurrLedState = RTW_LED_OFF; /*  Current LED state. */
  53        pLed->bLedOn = false; /*  true if LED is ON, false if LED is OFF. */
  54
  55        pLed->bLedBlinkInProgress = false; /*  true if it is blinking, false o.w.. */
  56        pLed->bLedWPSBlinkInProgress = false;
  57
  58        pLed->BlinkTimes = 0; /*  Number of times to toggle led state for blinking. */
  59        pLed->BlinkingLedState = LED_UNKNOWN; /*  Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
  60
  61        pLed->bLedNoLinkBlinkInProgress = false;
  62        pLed->bLedLinkBlinkInProgress = false;
  63        pLed->bLedStartToLinkBlinkInProgress = false;
  64        pLed->bLedScanBlinkInProgress = false;
  65}
  66
  67/*Description: */
  68/*              Initialize an LED_871x object. */
  69void InitLed871x(struct adapter *padapter, struct LED_871x *pLed)
  70{
  71        pLed->padapter = padapter;
  72
  73        ResetLedStatus(pLed);
  74
  75        setup_timer(&(pLed->BlinkTimer), BlinkTimerCallback,
  76                    (unsigned long)pLed);
  77
  78        INIT_WORK(&(pLed->BlinkWorkItem), BlinkWorkItemCallback);
  79}
  80
  81
  82/*  */
  83/*      Description: */
  84/*              DeInitialize an LED_871x object. */
  85/*  */
  86void DeInitLed871x(struct LED_871x *pLed)
  87{
  88        cancel_work_sync(&(pLed->BlinkWorkItem));
  89        del_timer_sync(&(pLed->BlinkTimer));
  90        ResetLedStatus(pLed);
  91}
  92
  93/*  */
  94/*      Description: */
  95/*              Implementation of LED blinking behavior. */
  96/*              It toggle off LED and schedule corresponding timer if necessary. */
  97/*  */
  98
  99static void SwLedBlink1(struct LED_871x *pLed)
 100{
 101        struct adapter *padapter = pLed->padapter;
 102        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 103        u8 bStopBlinking = false;
 104
 105        /*  Change LED according to BlinkingLedState specified. */
 106        if (pLed->BlinkingLedState == RTW_LED_ON) {
 107                SwLedOn(padapter, pLed);
 108                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
 109        } else {
 110                SwLedOff(padapter, pLed);
 111                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
 112        }
 113
 114        if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
 115                SwLedOff(padapter, pLed);
 116                ResetLedStatus(pLed);
 117                return;
 118        }
 119
 120        switch (pLed->CurrLedState) {
 121        case LED_BLINK_SLOWLY:
 122                if (pLed->bLedOn)
 123                        pLed->BlinkingLedState = RTW_LED_OFF;
 124                else
 125                        pLed->BlinkingLedState = RTW_LED_ON;
 126                mod_timer(&pLed->BlinkTimer, jiffies +
 127                          msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
 128                break;
 129        case LED_BLINK_NORMAL:
 130                if (pLed->bLedOn)
 131                        pLed->BlinkingLedState = RTW_LED_OFF;
 132                else
 133                        pLed->BlinkingLedState = RTW_LED_ON;
 134                mod_timer(&pLed->BlinkTimer, jiffies +
 135                          msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
 136                break;
 137        case LED_BLINK_SCAN:
 138                pLed->BlinkTimes--;
 139                if (pLed->BlinkTimes == 0)
 140                        bStopBlinking = true;
 141                if (bStopBlinking) {
 142                        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 143                                pLed->bLedLinkBlinkInProgress = true;
 144                                pLed->CurrLedState = LED_BLINK_NORMAL;
 145                                if (pLed->bLedOn)
 146                                        pLed->BlinkingLedState = RTW_LED_OFF;
 147                                else
 148                                        pLed->BlinkingLedState = RTW_LED_ON;
 149                                mod_timer(&pLed->BlinkTimer, jiffies +
 150                                          msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
 151                                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
 152                        } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
 153                                pLed->bLedNoLinkBlinkInProgress = true;
 154                                pLed->CurrLedState = LED_BLINK_SLOWLY;
 155                                if (pLed->bLedOn)
 156                                        pLed->BlinkingLedState = RTW_LED_OFF;
 157                                else
 158                                        pLed->BlinkingLedState = RTW_LED_ON;
 159                                mod_timer(&pLed->BlinkTimer, jiffies +
 160                                          msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
 161                                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
 162                        }
 163                        pLed->bLedScanBlinkInProgress = false;
 164                } else {
 165                        if (pLed->bLedOn)
 166                                pLed->BlinkingLedState = RTW_LED_OFF;
 167                        else
 168                                pLed->BlinkingLedState = RTW_LED_ON;
 169                        mod_timer(&pLed->BlinkTimer, jiffies +
 170                                  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
 171                }
 172                break;
 173        case LED_BLINK_TXRX:
 174                pLed->BlinkTimes--;
 175                if (pLed->BlinkTimes == 0)
 176                        bStopBlinking = true;
 177                if (bStopBlinking) {
 178                        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 179                                pLed->bLedLinkBlinkInProgress = true;
 180                                pLed->CurrLedState = LED_BLINK_NORMAL;
 181                                if (pLed->bLedOn)
 182                                        pLed->BlinkingLedState = RTW_LED_OFF;
 183                                else
 184                                        pLed->BlinkingLedState = RTW_LED_ON;
 185                                mod_timer(&pLed->BlinkTimer, jiffies +
 186                                          msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
 187                                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
 188                        } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
 189                                pLed->bLedNoLinkBlinkInProgress = true;
 190                                pLed->CurrLedState = LED_BLINK_SLOWLY;
 191                                if (pLed->bLedOn)
 192                                        pLed->BlinkingLedState = RTW_LED_OFF;
 193                                else
 194                                        pLed->BlinkingLedState = RTW_LED_ON;
 195                                mod_timer(&pLed->BlinkTimer, jiffies +
 196                                          msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
 197                                RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
 198                        }
 199                        pLed->BlinkTimes = 0;
 200                        pLed->bLedBlinkInProgress = false;
 201                } else {
 202                        if (pLed->bLedOn)
 203                                pLed->BlinkingLedState = RTW_LED_OFF;
 204                        else
 205                                pLed->BlinkingLedState = RTW_LED_ON;
 206                        mod_timer(&pLed->BlinkTimer, jiffies +
 207                                  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
 208                }
 209                break;
 210        case LED_BLINK_WPS:
 211                if (pLed->bLedOn)
 212                        pLed->BlinkingLedState = RTW_LED_OFF;
 213                else
 214                        pLed->BlinkingLedState = RTW_LED_ON;
 215                mod_timer(&pLed->BlinkTimer, jiffies +
 216                          msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
 217                break;
 218        case LED_BLINK_WPS_STOP:        /* WPS success */
 219                if (pLed->BlinkingLedState == RTW_LED_ON)
 220                        bStopBlinking = false;
 221                else
 222                        bStopBlinking = true;
 223
 224                if (bStopBlinking) {
 225                        pLed->bLedLinkBlinkInProgress = true;
 226                        pLed->CurrLedState = LED_BLINK_NORMAL;
 227                        if (pLed->bLedOn)
 228                                pLed->BlinkingLedState = RTW_LED_OFF;
 229                        else
 230                                pLed->BlinkingLedState = RTW_LED_ON;
 231                        mod_timer(&pLed->BlinkTimer, jiffies +
 232                                  msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
 233                        RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
 234
 235                        pLed->bLedWPSBlinkInProgress = false;
 236                } else {
 237                        pLed->BlinkingLedState = RTW_LED_OFF;
 238                        mod_timer(&pLed->BlinkTimer, jiffies +
 239                                  msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
 240                }
 241                break;
 242        default:
 243                break;
 244        }
 245}
 246
 247 /* ALPHA, added by chiyoko, 20090106 */
 248static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAction)
 249{
 250        struct led_priv *ledpriv = &(padapter->ledpriv);
 251        struct LED_871x *pLed = &(ledpriv->SwLed0);
 252        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 253
 254        switch (LedAction) {
 255        case LED_CTL_POWER_ON:
 256        case LED_CTL_START_TO_LINK:
 257        case LED_CTL_NO_LINK:
 258                if (!pLed->bLedNoLinkBlinkInProgress) {
 259                        if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
 260                                return;
 261                        if (pLed->bLedLinkBlinkInProgress) {
 262                                del_timer_sync(&(pLed->BlinkTimer));
 263                                pLed->bLedLinkBlinkInProgress = false;
 264                        }
 265                        if (pLed->bLedBlinkInProgress) {
 266                                del_timer_sync(&(pLed->BlinkTimer));
 267                                pLed->bLedBlinkInProgress = false;
 268                        }
 269
 270                        pLed->bLedNoLinkBlinkInProgress = true;
 271                        pLed->CurrLedState = LED_BLINK_SLOWLY;
 272                        if (pLed->bLedOn)
 273                                pLed->BlinkingLedState = RTW_LED_OFF;
 274                        else
 275                                pLed->BlinkingLedState = RTW_LED_ON;
 276                        mod_timer(&pLed->BlinkTimer, jiffies +
 277                                  msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
 278                }
 279                break;
 280        case LED_CTL_LINK:
 281                if (!pLed->bLedLinkBlinkInProgress) {
 282                        if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
 283                                return;
 284                        if (pLed->bLedNoLinkBlinkInProgress) {
 285                                del_timer_sync(&(pLed->BlinkTimer));
 286                                pLed->bLedNoLinkBlinkInProgress = false;
 287                        }
 288                        if (pLed->bLedBlinkInProgress) {
 289                                del_timer_sync(&(pLed->BlinkTimer));
 290                                pLed->bLedBlinkInProgress = false;
 291                        }
 292                        pLed->bLedLinkBlinkInProgress = true;
 293                        pLed->CurrLedState = LED_BLINK_NORMAL;
 294                        if (pLed->bLedOn)
 295                                pLed->BlinkingLedState = RTW_LED_OFF;
 296                        else
 297                                pLed->BlinkingLedState = RTW_LED_ON;
 298                        mod_timer(&pLed->BlinkTimer, jiffies +
 299                                  msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
 300                }
 301                break;
 302        case LED_CTL_SITE_SURVEY:
 303                if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED))) {
 304                        ;
 305                } else if (!pLed->bLedScanBlinkInProgress) {
 306                        if (IS_LED_WPS_BLINKING(pLed))
 307                                return;
 308                        if (pLed->bLedNoLinkBlinkInProgress) {
 309                                del_timer_sync(&(pLed->BlinkTimer));
 310                                pLed->bLedNoLinkBlinkInProgress = false;
 311                        }
 312                        if (pLed->bLedLinkBlinkInProgress) {
 313                                del_timer_sync(&(pLed->BlinkTimer));
 314                                 pLed->bLedLinkBlinkInProgress = false;
 315                        }
 316                        if (pLed->bLedBlinkInProgress) {
 317                                del_timer_sync(&(pLed->BlinkTimer));
 318                                pLed->bLedBlinkInProgress = false;
 319                        }
 320                        pLed->bLedScanBlinkInProgress = true;
 321                        pLed->CurrLedState = LED_BLINK_SCAN;
 322                        pLed->BlinkTimes = 24;
 323                        if (pLed->bLedOn)
 324                                pLed->BlinkingLedState = RTW_LED_OFF;
 325                        else
 326                                pLed->BlinkingLedState = RTW_LED_ON;
 327                        mod_timer(&pLed->BlinkTimer, jiffies +
 328                                  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
 329                 }
 330                break;
 331        case LED_CTL_TX:
 332        case LED_CTL_RX:
 333                if (!pLed->bLedBlinkInProgress) {
 334                        if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
 335                                return;
 336                        if (pLed->bLedNoLinkBlinkInProgress) {
 337                                del_timer_sync(&(pLed->BlinkTimer));
 338                                pLed->bLedNoLinkBlinkInProgress = false;
 339                        }
 340                        if (pLed->bLedLinkBlinkInProgress) {
 341                                del_timer_sync(&(pLed->BlinkTimer));
 342                                pLed->bLedLinkBlinkInProgress = false;
 343                        }
 344                        pLed->bLedBlinkInProgress = true;
 345                        pLed->CurrLedState = LED_BLINK_TXRX;
 346                        pLed->BlinkTimes = 2;
 347                        if (pLed->bLedOn)
 348                                pLed->BlinkingLedState = RTW_LED_OFF;
 349                        else
 350                                pLed->BlinkingLedState = RTW_LED_ON;
 351                        mod_timer(&pLed->BlinkTimer, jiffies +
 352                                  msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
 353                }
 354                break;
 355        case LED_CTL_START_WPS: /* wait until xinpin finish */
 356        case LED_CTL_START_WPS_BOTTON:
 357                 if (!pLed->bLedWPSBlinkInProgress) {
 358                        if (pLed->bLedNoLinkBlinkInProgress) {
 359                                del_timer_sync(&(pLed->BlinkTimer));
 360                                pLed->bLedNoLinkBlinkInProgress = false;
 361                        }
 362                        if (pLed->bLedLinkBlinkInProgress) {
 363                                del_timer_sync(&(pLed->BlinkTimer));
 364                                 pLed->bLedLinkBlinkInProgress = false;
 365                        }
 366                        if (pLed->bLedBlinkInProgress) {
 367                                del_timer_sync(&(pLed->BlinkTimer));
 368                                pLed->bLedBlinkInProgress = false;
 369                        }
 370                        if (pLed->bLedScanBlinkInProgress) {
 371                                del_timer_sync(&(pLed->BlinkTimer));
 372                                pLed->bLedScanBlinkInProgress = false;
 373                        }
 374                        pLed->bLedWPSBlinkInProgress = true;
 375                        pLed->CurrLedState = LED_BLINK_WPS;
 376                        if (pLed->bLedOn)
 377                                pLed->BlinkingLedState = RTW_LED_OFF;
 378                        else
 379                                pLed->BlinkingLedState = RTW_LED_ON;
 380                        mod_timer(&pLed->BlinkTimer, jiffies +
 381                                  msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
 382                 }
 383                break;
 384        case LED_CTL_STOP_WPS:
 385                if (pLed->bLedNoLinkBlinkInProgress) {
 386                        del_timer_sync(&(pLed->BlinkTimer));
 387                        pLed->bLedNoLinkBlinkInProgress = false;
 388                }
 389                if (pLed->bLedLinkBlinkInProgress) {
 390                        del_timer_sync(&(pLed->BlinkTimer));
 391                         pLed->bLedLinkBlinkInProgress = false;
 392                }
 393                if (pLed->bLedBlinkInProgress) {
 394                        del_timer_sync(&(pLed->BlinkTimer));
 395                        pLed->bLedBlinkInProgress = false;
 396                }
 397                if (pLed->bLedScanBlinkInProgress) {
 398                        del_timer_sync(&(pLed->BlinkTimer));
 399                        pLed->bLedScanBlinkInProgress = false;
 400                }
 401                if (pLed->bLedWPSBlinkInProgress)
 402                        del_timer_sync(&(pLed->BlinkTimer));
 403                else
 404                        pLed->bLedWPSBlinkInProgress = true;
 405                pLed->CurrLedState = LED_BLINK_WPS_STOP;
 406                if (pLed->bLedOn) {
 407                        pLed->BlinkingLedState = RTW_LED_OFF;
 408                        mod_timer(&pLed->BlinkTimer, jiffies +
 409                                  msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
 410                } else {
 411                        pLed->BlinkingLedState = RTW_LED_ON;
 412                        mod_timer(&pLed->BlinkTimer,
 413                                  jiffies + msecs_to_jiffies(0));
 414                }
 415                break;
 416        case LED_CTL_STOP_WPS_FAIL:
 417                if (pLed->bLedWPSBlinkInProgress) {
 418                        del_timer_sync(&(pLed->BlinkTimer));
 419                        pLed->bLedWPSBlinkInProgress = false;
 420                }
 421                pLed->bLedNoLinkBlinkInProgress = true;
 422                pLed->CurrLedState = LED_BLINK_SLOWLY;
 423                if (pLed->bLedOn)
 424                        pLed->BlinkingLedState = RTW_LED_OFF;
 425                else
 426                        pLed->BlinkingLedState = RTW_LED_ON;
 427                mod_timer(&pLed->BlinkTimer, jiffies +
 428                          msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
 429                break;
 430        case LED_CTL_POWER_OFF:
 431                pLed->CurrLedState = RTW_LED_OFF;
 432                pLed->BlinkingLedState = RTW_LED_OFF;
 433                if (pLed->bLedNoLinkBlinkInProgress) {
 434                        del_timer_sync(&(pLed->BlinkTimer));
 435                        pLed->bLedNoLinkBlinkInProgress = false;
 436                }
 437                if (pLed->bLedLinkBlinkInProgress) {
 438                        del_timer_sync(&(pLed->BlinkTimer));
 439                        pLed->bLedLinkBlinkInProgress = false;
 440                }
 441                if (pLed->bLedBlinkInProgress) {
 442                        del_timer_sync(&(pLed->BlinkTimer));
 443                        pLed->bLedBlinkInProgress = false;
 444                }
 445                if (pLed->bLedWPSBlinkInProgress) {
 446                        del_timer_sync(&(pLed->BlinkTimer));
 447                        pLed->bLedWPSBlinkInProgress = false;
 448                }
 449                if (pLed->bLedScanBlinkInProgress) {
 450                        del_timer_sync(&(pLed->BlinkTimer));
 451                        pLed->bLedScanBlinkInProgress = false;
 452                }
 453                SwLedOff(padapter, pLed);
 454                break;
 455        default:
 456                break;
 457        }
 458
 459        RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Led %d\n", pLed->CurrLedState));
 460}
 461
 462/*  */
 463/*      Description: */
 464/*              Handler function of LED Blinking. */
 465/*  */
 466void BlinkHandler(struct LED_871x *pLed)
 467{
 468        struct adapter *padapter = pLed->padapter;
 469
 470        if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
 471                return;
 472
 473        SwLedBlink1(pLed);
 474}
 475
 476void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction)
 477{
 478        struct led_priv *ledpriv = &(padapter->ledpriv);
 479
 480        if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped) ||
 481           (!padapter->hw_init_completed))
 482                return;
 483
 484        if (!ledpriv->bRegUseLed)
 485                return;
 486
 487        if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on &&
 488             padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) &&
 489            (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
 490             LedAction == LED_CTL_SITE_SURVEY ||
 491             LedAction == LED_CTL_LINK ||
 492             LedAction == LED_CTL_NO_LINK ||
 493             LedAction == LED_CTL_POWER_ON))
 494                return;
 495
 496        SwLedControlMode1(padapter, LedAction);
 497}
 498