Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / drivers / staging / otus / 80211core / ledmgr.c
1 /*
2  * Copyright (c) 2007-2008 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include "cprecomp.h"
18
19 /************************************************************************/
20 /*                                                                      */
21 /*    FUNCTION DESCRIPTION                  zfLedCtrlType1              */
22 /*      Traditional single-LED state                                    */
23 /*                                                                      */
24 /*    INPUTS                                                            */
25 /*      dev : device pointer                                            */
26 /*                                                                      */
27 /*    OUTPUTS                                                           */
28 /*      None                                                            */
29 /*                                                                      */
30 /*    AUTHOR                                                            */
31 /*      Stephen Chen        Atheros Communications, INC.    2007.6      */
32 /*                                                                      */
33 /************************************************************************/
34 // bit 15-12 : Toff for Scan state
35 //     11-8 : Ton for Scan state
36 //     7 : Reserved
37 //     6 : mode
38 //--------------------------------------
39 //     bit 6 = 0
40 //     5-4 : Connect state
41 //           00 => always off
42 //           01 => always on
43 //           10 => Idle off, acitve on
44 //           11 => Idle on, active off
45 //--------------------------------------
46 //     bit 6 = 1
47 //     5-4 : freq
48 //           00 => 1Hz
49 //           01 => 0.5Hz
50 //           10 => 0.25Hz
51 //           11 => 0.125Hz
52 //--------------------------------------
53 //     3 : Power save state
54 //         0 => always off in power save state
55 //         1 => works as connect state
56 //     2 : Disable state
57 //     1 : Reserved
58 //     0 : Power-on state
59 void zfLedCtrlType1(zdev_t* dev)
60 {
61     u16_t i;
62     u32_t ton, toff, tmp, period;
63     zmw_get_wlan_dev(dev);
64
65     for (i=0; i<ZM_MAX_LED_NUMBER; i++)
66     {
67         if (zfStaIsConnected(dev) != TRUE)
68         {
69             //Scan state
70             ton = ((wd->ledStruct.ledMode[i] & 0xf00) >> 8) * 5;
71             toff = ((wd->ledStruct.ledMode[i] & 0xf000) >> 12) * 5;
72
73             if ((ton + toff) != 0)
74             {
75                 tmp = wd->ledStruct.counter / (ton+toff);
76                 tmp = wd->ledStruct.counter - (tmp * (ton+toff));
77                 if (tmp < ton)
78                 {
79                     zfHpLedCtrl(dev, i, 1);
80                 }
81                 else
82                 {
83                     zfHpLedCtrl(dev, i, 0);
84                 }
85             }
86         }
87         else
88         {
89             if ((zfPowerSavingMgrIsSleeping(dev)) && ((wd->ledStruct.ledMode[i] & 0x8) == 0))
90             {
91                 zfHpLedCtrl(dev, i, 0);
92             }
93             else
94             {
95                 //Connect state
96                 if ((wd->ledStruct.ledMode[i] & 0x40) == 0)
97                 {
98                     if ((wd->ledStruct.counter & 1) == 0)
99                     {
100                         zfHpLedCtrl(dev, i, (wd->ledStruct.ledMode[i] & 0x10) >> 4);
101                     }
102                     else
103                     {
104                         if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
105                         {
106                             wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
107                             if ((wd->ledStruct.ledMode[i] & 0x20) != 0)
108                             {
109                                 zfHpLedCtrl(dev, i, ((wd->ledStruct.ledMode[i] & 0x10) >> 4)^1);
110                             }
111                         }
112                     }
113                 }// if ((wd->ledStruct.ledMode[i] & 0x40) == 0)
114                 else
115                 {
116                     period = 5 * (1 << ((wd->ledStruct.ledMode[i] & 0x30) >> 4));
117                     tmp = wd->ledStruct.counter / (period*2);
118                     tmp = wd->ledStruct.counter - (tmp * (period*2));
119                     if (tmp < period)
120                     {
121                         if ((wd->ledStruct.counter & 1) == 0)
122                         {
123                             zfHpLedCtrl(dev, i, 0);
124                         }
125                         else
126                         {
127                             if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
128                             {
129                                 wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
130                                 zfHpLedCtrl(dev, i, 1);
131                             }
132                         }
133                     }
134                     else
135                     {
136                         if ((wd->ledStruct.counter & 1) == 0)
137                         {
138                             zfHpLedCtrl(dev, i, 1);
139                         }
140                         else
141                         {
142                             if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
143                             {
144                                 wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
145                                 zfHpLedCtrl(dev, i, 0);
146                             }
147                         }
148                     }
149                 } //else, if ((wd->ledStruct.ledMode[i] & 0x40) == 0)
150             } //else, if (zfPowerSavingMgrIsSleeping(dev))
151         } //else : if (zfStaIsConnected(dev) != TRUE)
152     } //for (i=0; i<ZM_MAX_LED_NUMBER; i++)
153 }
154
155 /******************************************************************************/
156 /*                                                                            */
157 /*    FUNCTION DESCRIPTION                  zfLedCtrlType2                    */
158 /*      Customize for Netgear Dual-LED state ((bug#31292))                    */
159 /*                                                                            */
160 /*      1. Status:  When dongle does not connect to 2.4G or 5G but in site    */
161 /*                  survey/association                                        */
162 /*         LED status: Slow blinking, Amber then Blue per 500ms               */
163 /*      2. Status:      Connection at 2.4G in site survey/association             */
164 /*         LED status: Slow blinking, Amber/off per 500ms                     */
165 /*      3. Status:      Connection at 5G in site survey/association               */
166 /*         LED status: Slow blinking, Blue/off per 500ms                      */
167 /*      4. Status:      When transfer the packet                                  */
168 /*         LED status: Blink per packet, including TX and RX                  */
169 /*      5. Status:      When linking is established but no traffic                */
170 /*         LED status: Always on                                              */
171 /*      6. Status:      When linking is dropped but no re-connection              */
172 /*         LED status: Always off                                             */
173 /*      7. Status:      From one connection(2.4G or 5G) to change to another band */
174 /*         LED status: Amber/Blue =>Slow blinking, Amber then Blue per 500ms  */
175 /*                                                                            */
176 /*    INPUTS                                                                  */
177 /*      dev : device pointer                                                  */
178 /*                                                                            */
179 /*    OUTPUTS                                                                 */
180 /*      None                                                                  */
181 /*                                                                            */
182 /*    AUTHOR                                                                  */
183 /*      Shang-Chun Liu        Atheros Communications, INC.    2007.11         */
184 /*                                                                            */
185 /******************************************************************************/
186 void zfLedCtrlType2_scan(zdev_t* dev);
187
188 void zfLedCtrlType2(zdev_t* dev)
189 {
190     u16_t OperateLED;
191     zmw_get_wlan_dev(dev);
192
193     if (zfStaIsConnected(dev) != TRUE)
194     {
195         // Disconnect state
196         if(wd->ledStruct.counter % 4 != 0)
197         {
198             // Update LED each 400ms(4*100)
199             // Prevent this situation
200             //              _______         ___
201             // LED[0] ON   |       |       | x |
202             // ------ OFF->+-+-+-+-+-+-+-+-+-+-+-+->>>...
203             // LED[1] ON
204             //
205             return;
206         }
207
208         if (((wd->state == ZM_WLAN_STATE_DISABLED) && (wd->sta.bChannelScan))
209             || ((wd->state != ZM_WLAN_STATE_DISABLED) && (wd->sta.bAutoReconnect)))
210         {
211             // Scan/AutoReconnect state
212             zfLedCtrlType2_scan(dev);
213         }
214         else
215         {
216             // Neither Connected nor Scan
217             zfHpLedCtrl(dev, 0, 0);
218             zfHpLedCtrl(dev, 1, 0);
219         }
220     }
221     else
222     {
223         if( wd->sta.bChannelScan )
224         {
225             // Scan state
226             if(wd->ledStruct.counter % 4 != 0)
227                 return;
228             zfLedCtrlType2_scan(dev);
229             return;
230         }
231
232         if(wd->frequency < 3000)
233         {
234             OperateLED = 0;     // LED[0]: work on 2.4G (b/g band)
235             zfHpLedCtrl(dev, 1, 0);
236         }
237         else
238         {
239             OperateLED = 1;     // LED[1]: work on 5G (a band)
240             zfHpLedCtrl(dev, 0, 0);
241         }
242
243         if ((zfPowerSavingMgrIsSleeping(dev)) && ((wd->ledStruct.ledMode[OperateLED] & 0x8) == 0))
244         {
245             // If Sleeping, turn OFF
246             zfHpLedCtrl(dev, OperateLED, 0);
247         }
248         else
249         {
250             //Connect state
251             if ((wd->ledStruct.counter & 1) == 0)   // even
252             {
253                 // No traffic, always ON
254                 zfHpLedCtrl(dev, OperateLED, 1);
255             }
256             else       // odd
257             {
258                 if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
259                 {
260                     // If have traffic, turn OFF
261                             //                   _____   _   _   _   _____
262                             // LED[Operate] ON        | | | | | | | |
263                             // ------------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
264                             //
265                     wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
266                     zfHpLedCtrl(dev, OperateLED, 0);
267                 }
268             }
269         }
270     }
271 }
272
273 void zfLedCtrlType2_scan(zdev_t* dev)
274 {
275     zmw_get_wlan_dev(dev);
276
277     // When doing scan, blink(Amber/Blue) and off per 500ms (about 400ms in our driver)
278     //               _______                         _______
279     // LED[0] ON    |       |       8       12      |       |
280     // ------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
281     // LED[1] ON    0       4       |_______|       0       3
282     //
283
284     switch(wd->ledStruct.counter % 16)
285     {
286         case 0:   // case 0~3, LED[0] on
287             if(wd->supportMode & ZM_WIRELESS_MODE_24)
288             {
289                 zfHpLedCtrl(dev, 0, 1);
290                 zfHpLedCtrl(dev, 1, 0);
291             }
292             else
293             {
294                 zfHpLedCtrl(dev, 1, 1);
295                 zfHpLedCtrl(dev, 0, 0);
296             }
297             break;
298
299         case 8:   // case 8~11, LED[1] on
300             if(wd->supportMode & ZM_WIRELESS_MODE_5)
301             {
302                 zfHpLedCtrl(dev, 1, 1);
303                 zfHpLedCtrl(dev, 0, 0);
304             }
305             else
306             {
307                 zfHpLedCtrl(dev, 0, 1);
308                 zfHpLedCtrl(dev, 1, 0);
309             }
310             break;
311
312         default:  // others, all off
313             zfHpLedCtrl(dev, 0, 0);
314             zfHpLedCtrl(dev, 1, 0);
315             break;
316     }
317 }
318
319 /**********************************************************************************/
320 /*                                                                                */
321 /*    FUNCTION DESCRIPTION                  zfLedCtrlType3                        */
322 /*      Customize for Netgear Single-LED state ((bug#32243))                      */
323 /*                                                                                */
324 /*  Â¡EOff: when the adapter is disabled or hasn't started to associate with AP    */
325 /*         yet.                                                                          */
326 /*  Â¡EOn: Once adpater associate with AP successfully                             */
327 /*  Â¡ESlow blinking: whenever adapters do site-survey or try to associate with AP */
328 /*    - If there is a connection already, and adapters do site-survey or          */
329 /*      re-associate action, the LED should keep LED backgraoud as ON, thus       */
330 /*      the blinking behavior SHOULD be OFF (200ms) - ON (800ms) and continue this*/
331 /*      cycle.                                                                    */
332 /*    - If there is no connection yet, and adapters start to do site-survey or    */
333 /*      associate action, the LED should keep LED background as OFF, thus the     */
334 /*      blinking behavior SHOULD be ON (200ms) - OFF (800ms) and continue this    */
335 /*      cycle.                                                                    */
336 /*    - For the case that associate fail, adpater should keep associating, and the*/
337 /*      LED should also keep slow blinking.                                       */
338 /*  Â¡EQuick blinking: to blink OFF-ON cycle for each time that traffic packet is  */
339 /*    received or is transmitted.                                                 */
340 /*                                                                                */
341 /*    INPUTS                                                                      */
342 /*      dev : device pointer                                                      */
343 /*                                                                                */
344 /*    OUTPUTS                                                                     */
345 /*      None                                                                      */
346 /*                                                                                */
347 /*    AUTHOR                                                                      */
348 /*      Shang-Chun Liu        Atheros Communications, INC.    2008.01             */
349 /*                                                                                */
350 /**********************************************************************************/
351 void zfLedCtrlType3_scan(zdev_t* dev, u16_t isConnect);
352
353 void zfLedCtrlType3(zdev_t* dev)
354 {
355     zmw_get_wlan_dev(dev);
356
357     if (zfStaIsConnected(dev) != TRUE)
358     {
359         // Disconnect state
360         if(wd->ledStruct.counter % 2 != 0)
361         {
362             // Update LED each 200ms(2*100)
363             // Prevent this situation
364             //              ___     _
365             // LED[0] ON   |   |   |x|
366             // ------ OFF->+-+-+-+-+-+-+->>>...
367             //
368             return;
369         }
370
371         if (((wd->state == ZM_WLAN_STATE_DISABLED) && (wd->sta.bChannelScan))
372             || ((wd->state != ZM_WLAN_STATE_DISABLED) && (wd->sta.bAutoReconnect)))
373         {
374             // Scan/AutoReconnect state
375             zfLedCtrlType3_scan(dev, 0);
376         }
377         else
378         {
379             // Neither Connected nor Scan
380             zfHpLedCtrl(dev, 0, 0);
381             zfHpLedCtrl(dev, 1, 0);
382         }
383     }
384     else
385     {
386         if( wd->sta.bChannelScan )
387         {
388             // Scan state
389             if(wd->ledStruct.counter % 2 != 0)
390                 return;
391             zfLedCtrlType3_scan(dev, 1);
392             return;
393         }
394
395         if ((zfPowerSavingMgrIsSleeping(dev)) && ((wd->ledStruct.ledMode[0] & 0x8) == 0))
396         {
397             // If Sleeping, turn OFF
398             zfHpLedCtrl(dev, 0, 0);
399             zfHpLedCtrl(dev, 1, 0);
400         }
401         else
402         {
403             //Connect state
404             if ((wd->ledStruct.counter & 1) == 0)   // even
405             {
406                 // No traffic, always ON
407                 zfHpLedCtrl(dev, 0, 1);
408                 zfHpLedCtrl(dev, 1, 1);
409             }
410             else       // odd
411             {
412                 if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
413                 {
414                     // If have traffic, turn OFF
415                             //                   _____   _   _   _   _____
416                             // LED[Operate] ON        | | | | | | | |
417                             // ------------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
418                             //
419                     wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
420                     zfHpLedCtrl(dev, 0, 0);
421                     zfHpLedCtrl(dev, 1, 0);
422                 }
423             }
424         }
425     }
426 }
427
428 void zfLedCtrlType3_scan(zdev_t* dev, u16_t isConnect)
429 {
430     u32_t ton, toff, tmp;
431     zmw_get_wlan_dev(dev);
432
433     // Doing scan when :
434     // 1. Disconnected: ON (200ms) - OFF (800ms) (200ms-600ms in our driver)
435     //               ___             ___             ___
436     // LED[0] ON    |   |           |   |           |   |
437     // ------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
438     //              0   2   4   6   8  10  12  14  16
439     // 2. Connected:   ON (800ms) - OFF (200ms) (600ms-200ms in our driver)
440     //               ___________     ___________     ______
441     // LED[0] ON    |           |   |           |   |
442     // ------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
443     //              0   2   4   6   8  10  12  14  16
444
445     //Scan state
446     if(!isConnect)
447         ton = 2, toff = 6;
448     else
449         ton = 6, toff = 2;
450
451     if ((ton + toff) != 0)
452     {
453         tmp = wd->ledStruct.counter % (ton+toff);
454        if (tmp < ton)
455         {
456             zfHpLedCtrl(dev, 0, 1);
457             zfHpLedCtrl(dev, 1, 1);
458         }
459         else
460         {
461             zfHpLedCtrl(dev, 0, 0);
462             zfHpLedCtrl(dev, 1, 0);
463         }
464     }
465 }
466
467 /******************************************************************************/
468 /*                                                                            */
469 /*    FUNCTION DESCRIPTION                  zfLedCtrl_BlinkWhenScan_Alpha     */
470 /*      Customize for Alpha/DLink LED                                         */
471 /*      - Blink LED 12 times within 3 seconds when doing Active Scan          */
472 /*                            ___   ___   ___   ___                               */
473 /*            LED[0] ON      |   | |   | |   | |   |                              */
474 /*            -------OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+--+-->>>...                   */
475 /*                                                                            */
476 /*    INPUTS                                                                  */
477 /*      dev : device pointer                                                  */
478 /*                                                                            */
479 /*    OUTPUTS                                                                 */
480 /*      None                                                                  */
481 /*                                                                            */
482 /*    AUTHOR                                                                  */
483 /*      Shang-Chun Liu        Atheros Communications, INC.    2007.11         */
484 /*                                                                            */
485 /******************************************************************************/
486 void zfLedCtrl_BlinkWhenScan_Alpha(zdev_t* dev)
487 {
488     static u32_t counter = 0;
489     zmw_get_wlan_dev(dev);
490
491     if(counter > 34)        // counter for 3 sec
492     {
493         wd->ledStruct.LEDCtrlFlag &= ~(u8_t)ZM_LED_CTRL_FLAG_ALPHA;
494         counter = 0;
495     }
496
497     if( (counter % 3) < 2)
498         zfHpLedCtrl(dev, 0, 1);
499     else
500         zfHpLedCtrl(dev, 0, 0);
501
502     counter++;
503 }
504
505
506 /************************************************************************/
507 /*                                                                      */
508 /*    FUNCTION DESCRIPTION                  zfLed100msCtrl              */
509 /*      LED 100 milliseconds timer.                                     */
510 /*                                                                      */
511 /*    INPUTS                                                            */
512 /*      dev : device pointer                                            */
513 /*                                                                      */
514 /*    OUTPUTS                                                           */
515 /*      None                                                            */
516 /*                                                                      */
517 /*    AUTHOR                                                            */
518 /*      Stephen Chen        Atheros Communications, INC.    2007.6      */
519 /*                                                                      */
520 /************************************************************************/
521 void zfLed100msCtrl(zdev_t* dev)
522 {
523     zmw_get_wlan_dev(dev);
524
525     wd->ledStruct.counter++;
526
527     if(wd->ledStruct.LEDCtrlFlag)
528     {
529         switch(wd->ledStruct.LEDCtrlFlag) {
530         case ZM_LED_CTRL_FLAG_ALPHA:
531             zfLedCtrl_BlinkWhenScan_Alpha(dev);
532         break;
533         }
534     }
535     else
536     {
537         switch(wd->ledStruct.LEDCtrlType) {
538         case 1:                 // Traditional 1 LED
539             zfLedCtrlType1(dev);
540         break;
541
542         case 2:                 // Dual-LEDs for Netgear
543             zfLedCtrlType2(dev);
544         break;
545
546         case 3:                 // Single-LED for Netgear (WN111v2)
547             zfLedCtrlType3(dev);
548         break;
549
550         default:
551             zfLedCtrlType1(dev);
552         break;
553         }
554     }
555 }
556