rtw_led.c 15 KB

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