1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
6 ******************************************************************************/
13 /* Callback function of LED BlinkTimer, */
14 /* it just schedules to corresponding BlinkWorkItem/led_blink_hdl */
16 static void BlinkTimerCallback(struct timer_list *t)
18 struct LED_871x *pLed = from_timer(pLed, t, BlinkTimer);
19 struct adapter *padapter = pLed->padapter;
21 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
24 schedule_work(&pLed->BlinkWorkItem);
29 /* Callback function of LED BlinkWorkItem. */
31 void BlinkWorkItemCallback(struct work_struct *work)
33 struct LED_871x *pLed = container_of(work, struct LED_871x,
41 /* Reset status of LED_871x object. */
43 void ResetLedStatus(struct LED_871x *pLed)
45 pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */
46 pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */
48 pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */
49 pLed->bLedWPSBlinkInProgress = false;
51 pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */
52 pLed->BlinkingLedState = LED_UNKNOWN; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
54 pLed->bLedNoLinkBlinkInProgress = false;
55 pLed->bLedLinkBlinkInProgress = false;
56 pLed->bLedScanBlinkInProgress = false;
60 /* Initialize an LED_871x object. */
61 void InitLed871x(struct adapter *padapter, struct LED_871x *pLed)
63 pLed->padapter = padapter;
67 timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0);
69 INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback);
74 /* DeInitialize an LED_871x object. */
76 void DeInitLed871x(struct LED_871x *pLed)
78 cancel_work_sync(&pLed->BlinkWorkItem);
79 del_timer_sync(&pLed->BlinkTimer);
85 /* Implementation of LED blinking behavior. */
86 /* It toggle off LED and schedule corresponding timer if necessary. */
89 static void SwLedBlink1(struct LED_871x *pLed)
91 struct adapter *padapter = pLed->padapter;
92 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
93 u8 bStopBlinking = false;
95 /* Change LED according to BlinkingLedState specified. */
96 if (pLed->BlinkingLedState == RTW_LED_ON) {
97 sw_led_on(padapter, pLed);
98 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
99 ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
101 sw_led_off(padapter, pLed);
102 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
103 ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
106 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
107 sw_led_off(padapter, pLed);
108 ResetLedStatus(pLed);
112 switch (pLed->CurrLedState) {
113 case LED_BLINK_SLOWLY:
115 pLed->BlinkingLedState = RTW_LED_OFF;
117 pLed->BlinkingLedState = RTW_LED_ON;
118 mod_timer(&pLed->BlinkTimer, jiffies +
119 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
121 case LED_BLINK_NORMAL:
123 pLed->BlinkingLedState = RTW_LED_OFF;
125 pLed->BlinkingLedState = RTW_LED_ON;
126 mod_timer(&pLed->BlinkTimer, jiffies +
127 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
131 if (pLed->BlinkTimes == 0)
132 bStopBlinking = true;
134 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
135 pLed->bLedLinkBlinkInProgress = true;
136 pLed->CurrLedState = LED_BLINK_NORMAL;
138 pLed->BlinkingLedState = RTW_LED_OFF;
140 pLed->BlinkingLedState = RTW_LED_ON;
141 mod_timer(&pLed->BlinkTimer, jiffies +
142 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
143 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
144 } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
145 pLed->bLedNoLinkBlinkInProgress = true;
146 pLed->CurrLedState = LED_BLINK_SLOWLY;
148 pLed->BlinkingLedState = RTW_LED_OFF;
150 pLed->BlinkingLedState = RTW_LED_ON;
151 mod_timer(&pLed->BlinkTimer, jiffies +
152 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
153 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
155 pLed->bLedScanBlinkInProgress = false;
158 pLed->BlinkingLedState = RTW_LED_OFF;
160 pLed->BlinkingLedState = RTW_LED_ON;
161 mod_timer(&pLed->BlinkTimer, jiffies +
162 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
167 if (pLed->BlinkTimes == 0)
168 bStopBlinking = true;
170 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
171 pLed->bLedLinkBlinkInProgress = true;
172 pLed->CurrLedState = LED_BLINK_NORMAL;
174 pLed->BlinkingLedState = RTW_LED_OFF;
176 pLed->BlinkingLedState = RTW_LED_ON;
177 mod_timer(&pLed->BlinkTimer, jiffies +
178 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
179 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
180 } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
181 pLed->bLedNoLinkBlinkInProgress = true;
182 pLed->CurrLedState = LED_BLINK_SLOWLY;
184 pLed->BlinkingLedState = RTW_LED_OFF;
186 pLed->BlinkingLedState = RTW_LED_ON;
187 mod_timer(&pLed->BlinkTimer, jiffies +
188 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
189 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
191 pLed->BlinkTimes = 0;
192 pLed->bLedBlinkInProgress = false;
195 pLed->BlinkingLedState = RTW_LED_OFF;
197 pLed->BlinkingLedState = RTW_LED_ON;
198 mod_timer(&pLed->BlinkTimer, jiffies +
199 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
204 pLed->BlinkingLedState = RTW_LED_OFF;
206 pLed->BlinkingLedState = RTW_LED_ON;
207 mod_timer(&pLed->BlinkTimer, jiffies +
208 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
210 case LED_BLINK_WPS_STOP: /* WPS success */
211 if (pLed->BlinkingLedState == RTW_LED_ON)
212 bStopBlinking = false;
214 bStopBlinking = true;
217 pLed->bLedLinkBlinkInProgress = true;
218 pLed->CurrLedState = LED_BLINK_NORMAL;
220 pLed->BlinkingLedState = RTW_LED_OFF;
222 pLed->BlinkingLedState = RTW_LED_ON;
223 mod_timer(&pLed->BlinkTimer, jiffies +
224 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
225 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
227 pLed->bLedWPSBlinkInProgress = false;
229 pLed->BlinkingLedState = RTW_LED_OFF;
230 mod_timer(&pLed->BlinkTimer, jiffies +
231 msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
239 /* ALPHA, added by chiyoko, 20090106 */
240 static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAction)
242 struct led_priv *ledpriv = &padapter->ledpriv;
243 struct LED_871x *pLed = &ledpriv->sw_led;
244 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
247 case LED_CTL_POWER_ON:
248 case LED_CTL_START_TO_LINK:
249 case LED_CTL_NO_LINK:
250 if (pLed->bLedNoLinkBlinkInProgress)
252 if (pLed->CurrLedState == LED_BLINK_SCAN ||
253 IS_LED_WPS_BLINKING(pLed))
255 if (pLed->bLedLinkBlinkInProgress) {
256 del_timer_sync(&pLed->BlinkTimer);
257 pLed->bLedLinkBlinkInProgress = false;
259 if (pLed->bLedBlinkInProgress) {
260 del_timer_sync(&pLed->BlinkTimer);
261 pLed->bLedBlinkInProgress = false;
263 pLed->bLedNoLinkBlinkInProgress = true;
264 pLed->CurrLedState = LED_BLINK_SLOWLY;
266 pLed->BlinkingLedState = RTW_LED_OFF;
268 pLed->BlinkingLedState = RTW_LED_ON;
269 mod_timer(&pLed->BlinkTimer, jiffies +
270 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
273 if (pLed->bLedLinkBlinkInProgress)
275 if (pLed->CurrLedState == LED_BLINK_SCAN ||
276 IS_LED_WPS_BLINKING(pLed))
278 if (pLed->bLedNoLinkBlinkInProgress) {
279 del_timer_sync(&pLed->BlinkTimer);
280 pLed->bLedNoLinkBlinkInProgress = false;
282 if (pLed->bLedBlinkInProgress) {
283 del_timer_sync(&pLed->BlinkTimer);
284 pLed->bLedBlinkInProgress = false;
286 pLed->bLedLinkBlinkInProgress = true;
287 pLed->CurrLedState = LED_BLINK_NORMAL;
289 pLed->BlinkingLedState = RTW_LED_OFF;
291 pLed->BlinkingLedState = RTW_LED_ON;
292 mod_timer(&pLed->BlinkTimer, jiffies +
293 msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
295 case LED_CTL_SITE_SURVEY:
296 if (pmlmepriv->LinkDetectInfo.bBusyTraffic &&
297 check_fwstate(pmlmepriv, _FW_LINKED))
299 if (pLed->bLedScanBlinkInProgress)
301 if (IS_LED_WPS_BLINKING(pLed))
303 if (pLed->bLedNoLinkBlinkInProgress) {
304 del_timer_sync(&pLed->BlinkTimer);
305 pLed->bLedNoLinkBlinkInProgress = false;
307 if (pLed->bLedLinkBlinkInProgress) {
308 del_timer_sync(&pLed->BlinkTimer);
309 pLed->bLedLinkBlinkInProgress = false;
311 if (pLed->bLedBlinkInProgress) {
312 del_timer_sync(&pLed->BlinkTimer);
313 pLed->bLedBlinkInProgress = false;
315 pLed->bLedScanBlinkInProgress = true;
316 pLed->CurrLedState = LED_BLINK_SCAN;
317 pLed->BlinkTimes = 24;
319 pLed->BlinkingLedState = RTW_LED_OFF;
321 pLed->BlinkingLedState = RTW_LED_ON;
322 mod_timer(&pLed->BlinkTimer, jiffies +
323 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
327 if (pLed->bLedBlinkInProgress)
329 if (pLed->CurrLedState == LED_BLINK_SCAN ||
330 IS_LED_WPS_BLINKING(pLed))
332 if (pLed->bLedNoLinkBlinkInProgress) {
333 del_timer_sync(&pLed->BlinkTimer);
334 pLed->bLedNoLinkBlinkInProgress = false;
336 if (pLed->bLedLinkBlinkInProgress) {
337 del_timer_sync(&pLed->BlinkTimer);
338 pLed->bLedLinkBlinkInProgress = false;
340 pLed->bLedBlinkInProgress = true;
341 pLed->CurrLedState = LED_BLINK_TXRX;
342 pLed->BlinkTimes = 2;
344 pLed->BlinkingLedState = RTW_LED_OFF;
346 pLed->BlinkingLedState = RTW_LED_ON;
347 mod_timer(&pLed->BlinkTimer, jiffies +
348 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
350 case LED_CTL_START_WPS: /* wait until xinpin finish */
351 case LED_CTL_START_WPS_BOTTON:
352 if (pLed->bLedWPSBlinkInProgress)
354 if (pLed->bLedNoLinkBlinkInProgress) {
355 del_timer_sync(&pLed->BlinkTimer);
356 pLed->bLedNoLinkBlinkInProgress = false;
358 if (pLed->bLedLinkBlinkInProgress) {
359 del_timer_sync(&pLed->BlinkTimer);
360 pLed->bLedLinkBlinkInProgress = false;
362 if (pLed->bLedBlinkInProgress) {
363 del_timer_sync(&pLed->BlinkTimer);
364 pLed->bLedBlinkInProgress = false;
366 if (pLed->bLedScanBlinkInProgress) {
367 del_timer_sync(&pLed->BlinkTimer);
368 pLed->bLedScanBlinkInProgress = false;
370 pLed->bLedWPSBlinkInProgress = true;
371 pLed->CurrLedState = LED_BLINK_WPS;
373 pLed->BlinkingLedState = RTW_LED_OFF;
375 pLed->BlinkingLedState = RTW_LED_ON;
376 mod_timer(&pLed->BlinkTimer, jiffies +
377 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
379 case LED_CTL_STOP_WPS:
380 if (pLed->bLedNoLinkBlinkInProgress) {
381 del_timer_sync(&pLed->BlinkTimer);
382 pLed->bLedNoLinkBlinkInProgress = false;
384 if (pLed->bLedLinkBlinkInProgress) {
385 del_timer_sync(&pLed->BlinkTimer);
386 pLed->bLedLinkBlinkInProgress = false;
388 if (pLed->bLedBlinkInProgress) {
389 del_timer_sync(&pLed->BlinkTimer);
390 pLed->bLedBlinkInProgress = false;
392 if (pLed->bLedScanBlinkInProgress) {
393 del_timer_sync(&pLed->BlinkTimer);
394 pLed->bLedScanBlinkInProgress = false;
396 if (pLed->bLedWPSBlinkInProgress)
397 del_timer_sync(&pLed->BlinkTimer);
399 pLed->bLedWPSBlinkInProgress = true;
400 pLed->CurrLedState = LED_BLINK_WPS_STOP;
402 pLed->BlinkingLedState = RTW_LED_OFF;
403 mod_timer(&pLed->BlinkTimer, jiffies +
404 msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
406 pLed->BlinkingLedState = RTW_LED_ON;
407 mod_timer(&pLed->BlinkTimer,
408 jiffies + msecs_to_jiffies(0));
411 case LED_CTL_STOP_WPS_FAIL:
412 if (pLed->bLedWPSBlinkInProgress) {
413 del_timer_sync(&pLed->BlinkTimer);
414 pLed->bLedWPSBlinkInProgress = false;
416 pLed->bLedNoLinkBlinkInProgress = true;
417 pLed->CurrLedState = LED_BLINK_SLOWLY;
419 pLed->BlinkingLedState = RTW_LED_OFF;
421 pLed->BlinkingLedState = RTW_LED_ON;
422 mod_timer(&pLed->BlinkTimer, jiffies +
423 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
425 case LED_CTL_POWER_OFF:
426 pLed->CurrLedState = RTW_LED_OFF;
427 pLed->BlinkingLedState = RTW_LED_OFF;
428 if (pLed->bLedNoLinkBlinkInProgress) {
429 del_timer_sync(&pLed->BlinkTimer);
430 pLed->bLedNoLinkBlinkInProgress = false;
432 if (pLed->bLedLinkBlinkInProgress) {
433 del_timer_sync(&pLed->BlinkTimer);
434 pLed->bLedLinkBlinkInProgress = false;
436 if (pLed->bLedBlinkInProgress) {
437 del_timer_sync(&pLed->BlinkTimer);
438 pLed->bLedBlinkInProgress = false;
440 if (pLed->bLedWPSBlinkInProgress) {
441 del_timer_sync(&pLed->BlinkTimer);
442 pLed->bLedWPSBlinkInProgress = false;
444 if (pLed->bLedScanBlinkInProgress) {
445 del_timer_sync(&pLed->BlinkTimer);
446 pLed->bLedScanBlinkInProgress = false;
448 sw_led_off(padapter, pLed);
454 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
455 ("Led %d\n", pLed->CurrLedState));
458 void blink_handler(struct LED_871x *pLed)
460 struct adapter *padapter = pLed->padapter;
462 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
468 void led_control_8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction)
470 if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
471 !padapter->hw_init_completed)
474 if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on &&
475 padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) &&
476 (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
477 LedAction == LED_CTL_SITE_SURVEY ||
478 LedAction == LED_CTL_LINK ||
479 LedAction == LED_CTL_NO_LINK ||
480 LedAction == LED_CTL_POWER_ON))
483 SwLedControlMode1(padapter, LedAction);