1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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.
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
15 ******************************************************************************/
17 #include <drv_types.h>
22 /* Callback function of LED BlinkTimer, */
23 /* it just schedules to corresponding BlinkWorkItem/led_blink_hdl */
25 void BlinkTimerCallback(unsigned long data)
27 struct LED_871x *pLed = (struct LED_871x *)data;
28 struct adapter *padapter = pLed->padapter;
30 if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
33 schedule_work(&pLed->BlinkWorkItem);
38 /* Callback function of LED BlinkWorkItem. */
40 void BlinkWorkItemCallback(struct work_struct *work)
42 struct LED_871x *pLed = container_of(work, struct LED_871x,
50 /* Reset status of LED_871x object. */
52 void ResetLedStatus(struct LED_871x *pLed)
54 pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */
55 pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */
57 pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */
58 pLed->bLedWPSBlinkInProgress = false;
60 pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */
61 pLed->BlinkingLedState = LED_UNKNOWN; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
63 pLed->bLedNoLinkBlinkInProgress = false;
64 pLed->bLedLinkBlinkInProgress = false;
65 pLed->bLedScanBlinkInProgress = false;
69 /* Initialize an LED_871x object. */
70 void InitLed871x(struct adapter *padapter, struct LED_871x *pLed)
72 pLed->padapter = padapter;
76 setup_timer(&pLed->BlinkTimer, BlinkTimerCallback,
79 INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback);
85 /* DeInitialize an LED_871x object. */
87 void DeInitLed871x(struct LED_871x *pLed)
89 cancel_work_sync(&pLed->BlinkWorkItem);
90 del_timer_sync(&pLed->BlinkTimer);
96 /* Implementation of LED blinking behavior. */
97 /* It toggle off LED and schedule corresponding timer if necessary. */
100 static void SwLedBlink1(struct LED_871x *pLed)
102 struct adapter *padapter = pLed->padapter;
103 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
104 u8 bStopBlinking = false;
106 /* Change LED according to BlinkingLedState specified. */
107 if (pLed->BlinkingLedState == RTW_LED_ON) {
108 SwLedOn(padapter, pLed);
109 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
111 SwLedOff(padapter, pLed);
112 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
115 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
116 SwLedOff(padapter, pLed);
117 ResetLedStatus(pLed);
121 switch (pLed->CurrLedState) {
122 case LED_BLINK_SLOWLY:
124 pLed->BlinkingLedState = RTW_LED_OFF;
126 pLed->BlinkingLedState = RTW_LED_ON;
127 mod_timer(&pLed->BlinkTimer, jiffies +
128 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
130 case LED_BLINK_NORMAL:
132 pLed->BlinkingLedState = RTW_LED_OFF;
134 pLed->BlinkingLedState = RTW_LED_ON;
135 mod_timer(&pLed->BlinkTimer, jiffies +
136 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
140 if (pLed->BlinkTimes == 0)
141 bStopBlinking = true;
143 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
144 pLed->bLedLinkBlinkInProgress = true;
145 pLed->CurrLedState = LED_BLINK_NORMAL;
147 pLed->BlinkingLedState = RTW_LED_OFF;
149 pLed->BlinkingLedState = RTW_LED_ON;
150 mod_timer(&pLed->BlinkTimer, jiffies +
151 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
152 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
153 } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
154 pLed->bLedNoLinkBlinkInProgress = true;
155 pLed->CurrLedState = LED_BLINK_SLOWLY;
157 pLed->BlinkingLedState = RTW_LED_OFF;
159 pLed->BlinkingLedState = RTW_LED_ON;
160 mod_timer(&pLed->BlinkTimer, jiffies +
161 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
162 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
164 pLed->bLedScanBlinkInProgress = false;
167 pLed->BlinkingLedState = RTW_LED_OFF;
169 pLed->BlinkingLedState = RTW_LED_ON;
170 mod_timer(&pLed->BlinkTimer, jiffies +
171 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
176 if (pLed->BlinkTimes == 0)
177 bStopBlinking = true;
179 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
180 pLed->bLedLinkBlinkInProgress = true;
181 pLed->CurrLedState = LED_BLINK_NORMAL;
183 pLed->BlinkingLedState = RTW_LED_OFF;
185 pLed->BlinkingLedState = RTW_LED_ON;
186 mod_timer(&pLed->BlinkTimer, jiffies +
187 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
188 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
189 } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
190 pLed->bLedNoLinkBlinkInProgress = true;
191 pLed->CurrLedState = LED_BLINK_SLOWLY;
193 pLed->BlinkingLedState = RTW_LED_OFF;
195 pLed->BlinkingLedState = RTW_LED_ON;
196 mod_timer(&pLed->BlinkTimer, jiffies +
197 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
198 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
200 pLed->BlinkTimes = 0;
201 pLed->bLedBlinkInProgress = false;
204 pLed->BlinkingLedState = RTW_LED_OFF;
206 pLed->BlinkingLedState = RTW_LED_ON;
207 mod_timer(&pLed->BlinkTimer, jiffies +
208 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
213 pLed->BlinkingLedState = RTW_LED_OFF;
215 pLed->BlinkingLedState = RTW_LED_ON;
216 mod_timer(&pLed->BlinkTimer, jiffies +
217 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
219 case LED_BLINK_WPS_STOP: /* WPS success */
220 if (pLed->BlinkingLedState == RTW_LED_ON)
221 bStopBlinking = false;
223 bStopBlinking = true;
226 pLed->bLedLinkBlinkInProgress = true;
227 pLed->CurrLedState = LED_BLINK_NORMAL;
229 pLed->BlinkingLedState = RTW_LED_OFF;
231 pLed->BlinkingLedState = RTW_LED_ON;
232 mod_timer(&pLed->BlinkTimer, jiffies +
233 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
234 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
236 pLed->bLedWPSBlinkInProgress = false;
238 pLed->BlinkingLedState = RTW_LED_OFF;
239 mod_timer(&pLed->BlinkTimer, jiffies +
240 msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
248 /* ALPHA, added by chiyoko, 20090106 */
249 static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAction)
251 struct led_priv *ledpriv = &padapter->ledpriv;
252 struct LED_871x *pLed = &ledpriv->SwLed0;
253 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
256 case LED_CTL_POWER_ON:
257 case LED_CTL_START_TO_LINK:
258 case LED_CTL_NO_LINK:
259 if (!pLed->bLedNoLinkBlinkInProgress) {
260 if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
262 if (pLed->bLedLinkBlinkInProgress) {
263 del_timer_sync(&pLed->BlinkTimer);
264 pLed->bLedLinkBlinkInProgress = false;
266 if (pLed->bLedBlinkInProgress) {
267 del_timer_sync(&pLed->BlinkTimer);
268 pLed->bLedBlinkInProgress = false;
271 pLed->bLedNoLinkBlinkInProgress = true;
272 pLed->CurrLedState = LED_BLINK_SLOWLY;
274 pLed->BlinkingLedState = RTW_LED_OFF;
276 pLed->BlinkingLedState = RTW_LED_ON;
277 mod_timer(&pLed->BlinkTimer, jiffies +
278 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
282 if (!pLed->bLedLinkBlinkInProgress) {
283 if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
285 if (pLed->bLedNoLinkBlinkInProgress) {
286 del_timer_sync(&pLed->BlinkTimer);
287 pLed->bLedNoLinkBlinkInProgress = false;
289 if (pLed->bLedBlinkInProgress) {
290 del_timer_sync(&pLed->BlinkTimer);
291 pLed->bLedBlinkInProgress = false;
293 pLed->bLedLinkBlinkInProgress = true;
294 pLed->CurrLedState = LED_BLINK_NORMAL;
296 pLed->BlinkingLedState = RTW_LED_OFF;
298 pLed->BlinkingLedState = RTW_LED_ON;
299 mod_timer(&pLed->BlinkTimer, jiffies +
300 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
303 case LED_CTL_SITE_SURVEY:
304 if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED))) {
306 } else if (!pLed->bLedScanBlinkInProgress) {
307 if (IS_LED_WPS_BLINKING(pLed))
309 if (pLed->bLedNoLinkBlinkInProgress) {
310 del_timer_sync(&pLed->BlinkTimer);
311 pLed->bLedNoLinkBlinkInProgress = false;
313 if (pLed->bLedLinkBlinkInProgress) {
314 del_timer_sync(&pLed->BlinkTimer);
315 pLed->bLedLinkBlinkInProgress = false;
317 if (pLed->bLedBlinkInProgress) {
318 del_timer_sync(&pLed->BlinkTimer);
319 pLed->bLedBlinkInProgress = false;
321 pLed->bLedScanBlinkInProgress = true;
322 pLed->CurrLedState = LED_BLINK_SCAN;
323 pLed->BlinkTimes = 24;
325 pLed->BlinkingLedState = RTW_LED_OFF;
327 pLed->BlinkingLedState = RTW_LED_ON;
328 mod_timer(&pLed->BlinkTimer, jiffies +
329 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
334 if (!pLed->bLedBlinkInProgress) {
335 if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
337 if (pLed->bLedNoLinkBlinkInProgress) {
338 del_timer_sync(&pLed->BlinkTimer);
339 pLed->bLedNoLinkBlinkInProgress = false;
341 if (pLed->bLedLinkBlinkInProgress) {
342 del_timer_sync(&pLed->BlinkTimer);
343 pLed->bLedLinkBlinkInProgress = false;
345 pLed->bLedBlinkInProgress = true;
346 pLed->CurrLedState = LED_BLINK_TXRX;
347 pLed->BlinkTimes = 2;
349 pLed->BlinkingLedState = RTW_LED_OFF;
351 pLed->BlinkingLedState = RTW_LED_ON;
352 mod_timer(&pLed->BlinkTimer, jiffies +
353 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
356 case LED_CTL_START_WPS: /* wait until xinpin finish */
357 case LED_CTL_START_WPS_BOTTON:
358 if (!pLed->bLedWPSBlinkInProgress) {
359 if (pLed->bLedNoLinkBlinkInProgress) {
360 del_timer_sync(&pLed->BlinkTimer);
361 pLed->bLedNoLinkBlinkInProgress = false;
363 if (pLed->bLedLinkBlinkInProgress) {
364 del_timer_sync(&pLed->BlinkTimer);
365 pLed->bLedLinkBlinkInProgress = false;
367 if (pLed->bLedBlinkInProgress) {
368 del_timer_sync(&pLed->BlinkTimer);
369 pLed->bLedBlinkInProgress = false;
371 if (pLed->bLedScanBlinkInProgress) {
372 del_timer_sync(&pLed->BlinkTimer);
373 pLed->bLedScanBlinkInProgress = false;
375 pLed->bLedWPSBlinkInProgress = true;
376 pLed->CurrLedState = LED_BLINK_WPS;
378 pLed->BlinkingLedState = RTW_LED_OFF;
380 pLed->BlinkingLedState = RTW_LED_ON;
381 mod_timer(&pLed->BlinkTimer, jiffies +
382 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
385 case LED_CTL_STOP_WPS:
386 if (pLed->bLedNoLinkBlinkInProgress) {
387 del_timer_sync(&pLed->BlinkTimer);
388 pLed->bLedNoLinkBlinkInProgress = false;
390 if (pLed->bLedLinkBlinkInProgress) {
391 del_timer_sync(&pLed->BlinkTimer);
392 pLed->bLedLinkBlinkInProgress = false;
394 if (pLed->bLedBlinkInProgress) {
395 del_timer_sync(&pLed->BlinkTimer);
396 pLed->bLedBlinkInProgress = false;
398 if (pLed->bLedScanBlinkInProgress) {
399 del_timer_sync(&pLed->BlinkTimer);
400 pLed->bLedScanBlinkInProgress = false;
402 if (pLed->bLedWPSBlinkInProgress)
403 del_timer_sync(&pLed->BlinkTimer);
405 pLed->bLedWPSBlinkInProgress = true;
406 pLed->CurrLedState = LED_BLINK_WPS_STOP;
408 pLed->BlinkingLedState = RTW_LED_OFF;
409 mod_timer(&pLed->BlinkTimer, jiffies +
410 msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
412 pLed->BlinkingLedState = RTW_LED_ON;
413 mod_timer(&pLed->BlinkTimer,
414 jiffies + msecs_to_jiffies(0));
417 case LED_CTL_STOP_WPS_FAIL:
418 if (pLed->bLedWPSBlinkInProgress) {
419 del_timer_sync(&pLed->BlinkTimer);
420 pLed->bLedWPSBlinkInProgress = false;
422 pLed->bLedNoLinkBlinkInProgress = true;
423 pLed->CurrLedState = LED_BLINK_SLOWLY;
425 pLed->BlinkingLedState = RTW_LED_OFF;
427 pLed->BlinkingLedState = RTW_LED_ON;
428 mod_timer(&pLed->BlinkTimer, jiffies +
429 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
431 case LED_CTL_POWER_OFF:
432 pLed->CurrLedState = RTW_LED_OFF;
433 pLed->BlinkingLedState = RTW_LED_OFF;
434 if (pLed->bLedNoLinkBlinkInProgress) {
435 del_timer_sync(&pLed->BlinkTimer);
436 pLed->bLedNoLinkBlinkInProgress = false;
438 if (pLed->bLedLinkBlinkInProgress) {
439 del_timer_sync(&pLed->BlinkTimer);
440 pLed->bLedLinkBlinkInProgress = false;
442 if (pLed->bLedBlinkInProgress) {
443 del_timer_sync(&pLed->BlinkTimer);
444 pLed->bLedBlinkInProgress = false;
446 if (pLed->bLedWPSBlinkInProgress) {
447 del_timer_sync(&pLed->BlinkTimer);
448 pLed->bLedWPSBlinkInProgress = false;
450 if (pLed->bLedScanBlinkInProgress) {
451 del_timer_sync(&pLed->BlinkTimer);
452 pLed->bLedScanBlinkInProgress = false;
454 SwLedOff(padapter, pLed);
460 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Led %d\n", pLed->CurrLedState));
465 /* Handler function of LED Blinking. */
467 void BlinkHandler(struct LED_871x *pLed)
469 struct adapter *padapter = pLed->padapter;
471 if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
477 void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction)
479 if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped) ||
480 (!padapter->hw_init_completed))
483 if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on &&
484 padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) &&
485 (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
486 LedAction == LED_CTL_SITE_SURVEY ||
487 LedAction == LED_CTL_LINK ||
488 LedAction == LED_CTL_NO_LINK ||
489 LedAction == LED_CTL_POWER_ON))
492 SwLedControlMode1(padapter, LedAction);