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
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
21 #include <drv_types.h>
26 /* Callback function of LED BlinkTimer, */
27 /* it just schedules to corresponding BlinkWorkItem/led_blink_hdl */
29 void BlinkTimerCallback(void *data)
31 struct LED_871x *pLed = (struct LED_871x *)data;
32 struct adapter *padapter = pLed->padapter;
34 if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
37 schedule_work(&(pLed->BlinkWorkItem));
42 /* Callback function of LED BlinkWorkItem. */
44 void BlinkWorkItemCallback(struct work_struct *work)
46 struct LED_871x *pLed = container_of(work, struct LED_871x, BlinkWorkItem);
52 /* Reset status of LED_871x object. */
54 void ResetLedStatus(struct LED_871x *pLed)
56 pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */
57 pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */
59 pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */
60 pLed->bLedWPSBlinkInProgress = false;
62 pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */
63 pLed->BlinkingLedState = LED_UNKNOWN; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
65 pLed->bLedNoLinkBlinkInProgress = false;
66 pLed->bLedLinkBlinkInProgress = false;
67 pLed->bLedStartToLinkBlinkInProgress = false;
68 pLed->bLedScanBlinkInProgress = false;
72 /* Initialize an LED_871x object. */
73 void InitLed871x(struct adapter *padapter, struct LED_871x *pLed)
75 pLed->padapter = padapter;
79 _init_timer(&(pLed->BlinkTimer), padapter->pnetdev, BlinkTimerCallback, pLed);
81 INIT_WORK(&(pLed->BlinkWorkItem), BlinkWorkItemCallback);
87 /* DeInitialize an LED_871x object. */
89 void DeInitLed871x(struct LED_871x *pLed)
91 _cancel_workitem_sync(&(pLed->BlinkWorkItem));
92 _cancel_timer_ex(&(pLed->BlinkTimer));
98 /* Implementation of LED blinking behavior. */
99 /* It toggle off LED and schedule corresponding timer if necessary. */
102 static void SwLedBlink1(struct LED_871x *pLed)
104 struct adapter *padapter = pLed->padapter;
105 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
106 u8 bStopBlinking = false;
108 /* Change LED according to BlinkingLedState specified. */
109 if (pLed->BlinkingLedState == RTW_LED_ON) {
110 SwLedOn(padapter, pLed);
111 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
113 SwLedOff(padapter, pLed);
114 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
117 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
118 SwLedOff(padapter, pLed);
119 ResetLedStatus(pLed);
123 switch (pLed->CurrLedState) {
124 case LED_BLINK_SLOWLY:
126 pLed->BlinkingLedState = RTW_LED_OFF;
128 pLed->BlinkingLedState = RTW_LED_ON;
129 _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
131 case LED_BLINK_NORMAL:
133 pLed->BlinkingLedState = RTW_LED_OFF;
135 pLed->BlinkingLedState = RTW_LED_ON;
136 _set_timer(&(pLed->BlinkTimer), 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 _set_timer(&(pLed->BlinkTimer), 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;
156 pLed->BlinkingLedState = RTW_LED_OFF;
158 pLed->BlinkingLedState = RTW_LED_ON;
159 _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
160 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
162 pLed->bLedScanBlinkInProgress = false;
165 pLed->BlinkingLedState = RTW_LED_OFF;
167 pLed->BlinkingLedState = RTW_LED_ON;
168 _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
173 if (pLed->BlinkTimes == 0)
174 bStopBlinking = true;
176 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
177 pLed->bLedLinkBlinkInProgress = true;
178 pLed->CurrLedState = LED_BLINK_NORMAL;
180 pLed->BlinkingLedState = RTW_LED_OFF;
182 pLed->BlinkingLedState = RTW_LED_ON;
183 _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
184 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
185 } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
186 pLed->bLedNoLinkBlinkInProgress = true;
187 pLed->CurrLedState = LED_BLINK_SLOWLY;
189 pLed->BlinkingLedState = RTW_LED_OFF;
191 pLed->BlinkingLedState = RTW_LED_ON;
192 _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
193 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
195 pLed->BlinkTimes = 0;
196 pLed->bLedBlinkInProgress = false;
199 pLed->BlinkingLedState = RTW_LED_OFF;
201 pLed->BlinkingLedState = RTW_LED_ON;
202 _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
207 pLed->BlinkingLedState = RTW_LED_OFF;
209 pLed->BlinkingLedState = RTW_LED_ON;
210 _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
212 case LED_BLINK_WPS_STOP: /* WPS success */
213 if (pLed->BlinkingLedState == RTW_LED_ON)
214 bStopBlinking = false;
216 bStopBlinking = true;
219 pLed->bLedLinkBlinkInProgress = true;
220 pLed->CurrLedState = LED_BLINK_NORMAL;
222 pLed->BlinkingLedState = RTW_LED_OFF;
224 pLed->BlinkingLedState = RTW_LED_ON;
225 _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
226 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
228 pLed->bLedWPSBlinkInProgress = false;
230 pLed->BlinkingLedState = RTW_LED_OFF;
231 _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_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->SwLed0);
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) {
251 if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
253 if (pLed->bLedLinkBlinkInProgress) {
254 _cancel_timer_ex(&(pLed->BlinkTimer));
255 pLed->bLedLinkBlinkInProgress = false;
257 if (pLed->bLedBlinkInProgress) {
258 _cancel_timer_ex(&(pLed->BlinkTimer));
259 pLed->bLedBlinkInProgress = false;
262 pLed->bLedNoLinkBlinkInProgress = true;
263 pLed->CurrLedState = LED_BLINK_SLOWLY;
265 pLed->BlinkingLedState = RTW_LED_OFF;
267 pLed->BlinkingLedState = RTW_LED_ON;
268 _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
272 if (!pLed->bLedLinkBlinkInProgress) {
273 if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
275 if (pLed->bLedNoLinkBlinkInProgress) {
276 _cancel_timer_ex(&(pLed->BlinkTimer));
277 pLed->bLedNoLinkBlinkInProgress = false;
279 if (pLed->bLedBlinkInProgress) {
280 _cancel_timer_ex(&(pLed->BlinkTimer));
281 pLed->bLedBlinkInProgress = false;
283 pLed->bLedLinkBlinkInProgress = true;
284 pLed->CurrLedState = LED_BLINK_NORMAL;
286 pLed->BlinkingLedState = RTW_LED_OFF;
288 pLed->BlinkingLedState = RTW_LED_ON;
289 _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
292 case LED_CTL_SITE_SURVEY:
293 if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED))) {
295 } else if (!pLed->bLedScanBlinkInProgress) {
296 if (IS_LED_WPS_BLINKING(pLed))
298 if (pLed->bLedNoLinkBlinkInProgress) {
299 _cancel_timer_ex(&(pLed->BlinkTimer));
300 pLed->bLedNoLinkBlinkInProgress = false;
302 if (pLed->bLedLinkBlinkInProgress) {
303 _cancel_timer_ex(&(pLed->BlinkTimer));
304 pLed->bLedLinkBlinkInProgress = false;
306 if (pLed->bLedBlinkInProgress) {
307 _cancel_timer_ex(&(pLed->BlinkTimer));
308 pLed->bLedBlinkInProgress = false;
310 pLed->bLedScanBlinkInProgress = true;
311 pLed->CurrLedState = LED_BLINK_SCAN;
312 pLed->BlinkTimes = 24;
314 pLed->BlinkingLedState = RTW_LED_OFF;
316 pLed->BlinkingLedState = RTW_LED_ON;
317 _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
322 if (!pLed->bLedBlinkInProgress) {
323 if (pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
325 if (pLed->bLedNoLinkBlinkInProgress) {
326 _cancel_timer_ex(&(pLed->BlinkTimer));
327 pLed->bLedNoLinkBlinkInProgress = false;
329 if (pLed->bLedLinkBlinkInProgress) {
330 _cancel_timer_ex(&(pLed->BlinkTimer));
331 pLed->bLedLinkBlinkInProgress = false;
333 pLed->bLedBlinkInProgress = true;
334 pLed->CurrLedState = LED_BLINK_TXRX;
335 pLed->BlinkTimes = 2;
337 pLed->BlinkingLedState = RTW_LED_OFF;
339 pLed->BlinkingLedState = RTW_LED_ON;
340 _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
343 case LED_CTL_START_WPS: /* wait until xinpin finish */
344 case LED_CTL_START_WPS_BOTTON:
345 if (!pLed->bLedWPSBlinkInProgress) {
346 if (pLed->bLedNoLinkBlinkInProgress) {
347 _cancel_timer_ex(&(pLed->BlinkTimer));
348 pLed->bLedNoLinkBlinkInProgress = false;
350 if (pLed->bLedLinkBlinkInProgress) {
351 _cancel_timer_ex(&(pLed->BlinkTimer));
352 pLed->bLedLinkBlinkInProgress = false;
354 if (pLed->bLedBlinkInProgress) {
355 _cancel_timer_ex(&(pLed->BlinkTimer));
356 pLed->bLedBlinkInProgress = false;
358 if (pLed->bLedScanBlinkInProgress) {
359 _cancel_timer_ex(&(pLed->BlinkTimer));
360 pLed->bLedScanBlinkInProgress = false;
362 pLed->bLedWPSBlinkInProgress = true;
363 pLed->CurrLedState = LED_BLINK_WPS;
365 pLed->BlinkingLedState = RTW_LED_OFF;
367 pLed->BlinkingLedState = RTW_LED_ON;
368 _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
371 case LED_CTL_STOP_WPS:
372 if (pLed->bLedNoLinkBlinkInProgress) {
373 _cancel_timer_ex(&(pLed->BlinkTimer));
374 pLed->bLedNoLinkBlinkInProgress = false;
376 if (pLed->bLedLinkBlinkInProgress) {
377 _cancel_timer_ex(&(pLed->BlinkTimer));
378 pLed->bLedLinkBlinkInProgress = false;
380 if (pLed->bLedBlinkInProgress) {
381 _cancel_timer_ex(&(pLed->BlinkTimer));
382 pLed->bLedBlinkInProgress = false;
384 if (pLed->bLedScanBlinkInProgress) {
385 _cancel_timer_ex(&(pLed->BlinkTimer));
386 pLed->bLedScanBlinkInProgress = false;
388 if (pLed->bLedWPSBlinkInProgress)
389 _cancel_timer_ex(&(pLed->BlinkTimer));
391 pLed->bLedWPSBlinkInProgress = true;
392 pLed->CurrLedState = LED_BLINK_WPS_STOP;
394 pLed->BlinkingLedState = RTW_LED_OFF;
395 _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
397 pLed->BlinkingLedState = RTW_LED_ON;
398 _set_timer(&(pLed->BlinkTimer), 0);
401 case LED_CTL_STOP_WPS_FAIL:
402 if (pLed->bLedWPSBlinkInProgress) {
403 _cancel_timer_ex(&(pLed->BlinkTimer));
404 pLed->bLedWPSBlinkInProgress = false;
406 pLed->bLedNoLinkBlinkInProgress = true;
407 pLed->CurrLedState = LED_BLINK_SLOWLY;
409 pLed->BlinkingLedState = RTW_LED_OFF;
411 pLed->BlinkingLedState = RTW_LED_ON;
412 _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
414 case LED_CTL_POWER_OFF:
415 pLed->CurrLedState = RTW_LED_OFF;
416 pLed->BlinkingLedState = RTW_LED_OFF;
417 if (pLed->bLedNoLinkBlinkInProgress) {
418 _cancel_timer_ex(&(pLed->BlinkTimer));
419 pLed->bLedNoLinkBlinkInProgress = false;
421 if (pLed->bLedLinkBlinkInProgress) {
422 _cancel_timer_ex(&(pLed->BlinkTimer));
423 pLed->bLedLinkBlinkInProgress = false;
425 if (pLed->bLedBlinkInProgress) {
426 _cancel_timer_ex(&(pLed->BlinkTimer));
427 pLed->bLedBlinkInProgress = false;
429 if (pLed->bLedWPSBlinkInProgress) {
430 _cancel_timer_ex(&(pLed->BlinkTimer));
431 pLed->bLedWPSBlinkInProgress = false;
433 if (pLed->bLedScanBlinkInProgress) {
434 _cancel_timer_ex(&(pLed->BlinkTimer));
435 pLed->bLedScanBlinkInProgress = false;
437 SwLedOff(padapter, pLed);
443 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Led %d\n", pLed->CurrLedState));
448 /* Handler function of LED Blinking. */
450 void BlinkHandler(struct LED_871x *pLed)
452 struct adapter *padapter = pLed->padapter;
454 if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
460 void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction)
462 struct led_priv *ledpriv = &(padapter->ledpriv);
464 if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped) ||
465 (!padapter->hw_init_completed))
468 if (!ledpriv->bRegUseLed)
471 if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on &&
472 padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) &&
473 (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
474 LedAction == LED_CTL_SITE_SURVEY ||
475 LedAction == LED_CTL_LINK ||
476 LedAction == LED_CTL_NO_LINK ||
477 LedAction == LED_CTL_POWER_ON))
480 SwLedControlMode1(padapter, LedAction);