• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/otus/80211core/
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/*  Module Name : mm.c                                                  */
18/*                                                                      */
19/*  Abstract                                                            */
20/*      This module contains common functions for handle AP             */
21/*      management frame.                                               */
22/*                                                                      */
23/*  NOTES                                                               */
24/*      None                                                            */
25/*                                                                      */
26/************************************************************************/
27#include "cprecomp.h"
28#include "ratectrl.h"
29
30extern const u8_t zcUpToAc[];
31
32void zfMmApTimeTick(zdev_t* dev)
33{
34    u32_t now;
35    zmw_get_wlan_dev(dev);
36
37    //zm_debug_msg1("wd->wlanMode : ", wd->wlanMode);
38    if (wd->wlanMode == ZM_MODE_AP)
39    {
40        /* => every 1.28 seconds */
41        /* AP : aging STA that does not active for wd->ap.staAgingTime    */
42        now = wd->tick & 0x7f;
43        if (now == 0x0)
44        {
45            zfApAgingSta(dev);
46        }
47        else if (now == 0x1f)
48        {
49            zfQueueAge(dev, wd->ap.uapsdQ, wd->tick, 10000);
50        }
51        /* AP : check (wd->ap.protectedObss) and (wd->ap.bStaAssociated)  */
52        /*      to enable NonErp and Protection mode                      */
53        else if (now == 0x3f)
54        {
55            //zfApProtctionMonitor(dev);
56        }
57    }
58}
59
60/************************************************************************/
61/*                                                                      */
62/*    FUNCTION DESCRIPTION                  zfApInitStaTbl              */
63/*      Init AP's station table.                                        */
64/*                                                                      */
65/*    INPUTS                                                            */
66/*      dev : device pointer                                            */
67/*                                                                      */
68/*    OUTPUTS                                                           */
69/*      None                                                            */
70/*                                                                      */
71/*    AUTHOR                                                            */
72/*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
73/*                                                                      */
74/************************************************************************/
75void zfApInitStaTbl(zdev_t* dev)
76{
77    u16_t i;
78
79    zmw_get_wlan_dev(dev);
80
81    for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
82    {
83        wd->ap.staTable[i].valid = 0;
84        wd->ap.staTable[i].state = 0;
85        wd->ap.staTable[i].addr[0] = 0;
86        wd->ap.staTable[i].addr[1] = 0;
87        wd->ap.staTable[i].addr[2] = 0;
88        wd->ap.staTable[i].time = 0;
89        wd->ap.staTable[i].vap = 0;
90        wd->ap.staTable[i].encryMode = ZM_NO_WEP;
91    }
92    return;
93}
94
95
96/************************************************************************/
97/*                                                                      */
98/*    FUNCTION DESCRIPTION                  zfApFindSta                 */
99/*      Find a STA in station table.                                    */
100/*                                                                      */
101/*    INPUTS                                                            */
102/*      dev : device pointer                                            */
103/*      addr : Target STA address                                       */
104/*                                                                      */
105/*    OUTPUTS                                                           */
106/*      0xffff : fail                                                   */
107/*      other : STA table index                                         */
108/*                                                                      */
109/*    AUTHOR                                                            */
110/*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
111/*                                                                      */
112/************************************************************************/
113u16_t zfApFindSta(zdev_t* dev, u16_t* addr)
114{
115    u16_t i;
116
117    zmw_get_wlan_dev(dev);
118
119    for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
120    {
121        if (wd->ap.staTable[i].valid == 1)
122        {
123            if ((wd->ap.staTable[i].addr[0] == addr[0])
124                    && (wd->ap.staTable[i].addr[1] == addr[1])
125                    && (wd->ap.staTable[i].addr[2] == addr[2]))
126            {
127                return i;
128            }
129        }
130    }
131    return 0xffff;
132}
133
134u16_t zfApGetSTAInfo(zdev_t* dev, u16_t* addr, u16_t* state, u8_t* vap)
135{
136    u16_t id;
137
138    zmw_get_wlan_dev(dev);
139
140    zmw_declare_for_critical_section();
141
142    zmw_enter_critical_section(dev);
143
144    id = zfApFindSta(dev, addr);
145    if (id != 0xffff)
146    {
147        *vap = wd->ap.staTable[id].vap;
148        *state = wd->ap.staTable[id++].state;
149    }
150
151    zmw_leave_critical_section(dev);
152
153    return id;
154}
155
156
157void zfApGetStaQosType(zdev_t* dev, u16_t* addr, u8_t* qosType)
158{
159    u16_t id;
160
161    zmw_get_wlan_dev(dev);
162
163    zmw_declare_for_critical_section();
164
165    zmw_enter_critical_section(dev);
166
167    id = zfApFindSta(dev, addr);
168    if (id != 0xffff)
169    {
170        *qosType = wd->ap.staTable[id].qosType;
171    }
172    else
173    {
174        *qosType = 0;
175    }
176
177    zmw_leave_critical_section(dev);
178
179    return;
180}
181
182void zfApGetStaTxRateAndQosType(zdev_t* dev, u16_t* addr, u32_t* phyCtrl,
183                                u8_t* qosType, u16_t* rcProbingFlag)
184{
185    u16_t id;
186    u8_t rate;
187
188    zmw_get_wlan_dev(dev);
189
190    zmw_declare_for_critical_section();
191
192    zmw_enter_critical_section(dev);
193
194    id = zfApFindSta(dev, addr);
195    if (id != 0xffff)
196    {
197        rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->ap.staTable[id].rcCell, rcProbingFlag);
198#ifdef ZM_AP_DEBUG
199        //rate = 15;
200#endif
201        *phyCtrl = zcRateToPhyCtrl[rate];
202        *qosType = wd->ap.staTable[id].qosType;
203    }
204    else
205    {
206        if (wd->frequency < 3000)
207        {
208            /* CCK 1M */
209            //header[2] = 0x0f00;          //PHY control L
210            //header[3] = 0x0000;          //PHY control H
211            *phyCtrl = 0x00000F00;
212        }
213        else
214        {
215            /* CCK 6M */
216            //header[2] = 0x0f01;          //PHY control L
217            //header[3] = 0x000B;          //PHY control H
218            *phyCtrl = 0x000B0F01;
219        }
220        *qosType = 0;
221    }
222
223    zmw_leave_critical_section(dev);
224
225    zm_msg2_mm(ZM_LV_3, "PhyCtrl=", *phyCtrl);
226    return;
227}
228
229void zfApGetStaEncryType(zdev_t* dev, u16_t* addr, u8_t* encryType)
230{
231    //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
232    u16_t id;
233
234    zmw_get_wlan_dev(dev);
235
236    zmw_declare_for_critical_section();
237
238    zmw_enter_critical_section(dev);
239
240    id = zfApFindSta(dev, addr);
241    if (id != 0xffff)
242    {
243        *encryType = wd->ap.staTable[id].encryMode;
244    }
245    else
246    {
247        *encryType = ZM_NO_WEP;
248    }
249
250    zmw_leave_critical_section(dev);
251
252    zm_msg2_mm(ZM_LV_3, "encyrType=", *encryType);
253    return;
254}
255
256void zfApGetStaWpaIv(zdev_t* dev, u16_t* addr, u16_t* iv16, u32_t* iv32)
257{
258    //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
259    u16_t id;
260
261    zmw_get_wlan_dev(dev);
262
263    zmw_declare_for_critical_section();
264
265    zmw_enter_critical_section(dev);
266
267    id = zfApFindSta(dev, addr);
268    if (id != 0xffff)
269    {
270        *iv16 = wd->ap.staTable[id].iv16;
271        *iv32 = wd->ap.staTable[id].iv32;
272    }
273    else
274    {
275        *iv16 = 0;
276        *iv32 = 0;
277    }
278
279    zmw_leave_critical_section(dev);
280
281    zm_msg2_mm(ZM_LV_3, "iv16=", *iv16);
282    zm_msg2_mm(ZM_LV_3, "iv32=", *iv32);
283    return;
284}
285
286void zfApSetStaWpaIv(zdev_t* dev, u16_t* addr, u16_t iv16, u32_t iv32)
287{
288    //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
289    u16_t id;
290
291    zmw_get_wlan_dev(dev);
292
293    zmw_declare_for_critical_section();
294
295    zmw_enter_critical_section(dev);
296
297    id = zfApFindSta(dev, addr);
298    if (id != 0xffff)
299    {
300        wd->ap.staTable[id].iv16 = iv16;
301        wd->ap.staTable[id].iv32 = iv32;
302    }
303
304    zmw_leave_critical_section(dev);
305
306    zm_msg2_mm(ZM_LV_3, "iv16=", iv16);
307    zm_msg2_mm(ZM_LV_3, "iv32=", iv32);
308    return;
309}
310
311void zfApClearStaKey(zdev_t* dev, u16_t* addr)
312{
313    //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
314    u16_t bcAddr[3] = { 0xffff, 0xffff, 0xffff };
315    u16_t id;
316
317    zmw_get_wlan_dev(dev);
318
319    if (zfMemoryIsEqual((u8_t*)bcAddr, (u8_t*)addr, sizeof(bcAddr)) == TRUE)
320    {
321        /* Turn off group key information */
322    //    zfClearKey(dev, 0);
323    }
324    else
325    {
326        zmw_declare_for_critical_section();
327
328        zmw_enter_critical_section(dev);
329
330        id = zfApFindSta(dev, addr);
331        if (id != 0xffff)
332        {
333            /* Turn off STA's key information */
334            zfHpRemoveKey(dev, id+1);
335
336            /* Update STA's Encryption Type */
337            wd->ap.staTable[id].encryMode = ZM_NO_WEP;
338        }
339        else
340        {
341            zm_msg0_mm(ZM_LV_3, "Can't find STA address\n");
342        }
343        zmw_leave_critical_section(dev);
344    }
345}
346
347#ifdef ZM_ENABLE_CENC
348void zfApGetStaCencIvAndKeyIdx(zdev_t* dev, u16_t* addr, u32_t *iv, u8_t *keyIdx)
349{
350    //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
351    u16_t id;
352    zmw_get_wlan_dev(dev);
353    zmw_declare_for_critical_section();
354
355
356    zmw_enter_critical_section(dev);
357
358    id = zfApFindSta(dev, addr);
359    if (id != 0xffff)
360    {
361        *iv++ = wd->ap.staTable[id].txiv[0];
362        *iv++ = wd->ap.staTable[id].txiv[1];
363        *iv++ = wd->ap.staTable[id].txiv[2];
364        *iv = wd->ap.staTable[id].txiv[3];
365        *keyIdx = wd->ap.staTable[id].cencKeyIdx;
366    }
367    else
368    {
369        *iv++ = 0x5c365c37;
370        *iv++ = 0x5c365c36;
371        *iv++ = 0x5c365c36;
372        *iv = 0x5c365c36;
373        *keyIdx = 0;
374    }
375
376    zmw_leave_critical_section(dev);
377    return;
378}
379
380void zfApSetStaCencIv(zdev_t* dev, u16_t* addr, u32_t *iv)
381{
382    //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
383    u16_t id;
384    zmw_get_wlan_dev(dev);
385    zmw_declare_for_critical_section();
386
387
388    zmw_enter_critical_section(dev);
389
390    id = zfApFindSta(dev, addr);
391    if (id != 0xffff)
392    {
393        wd->ap.staTable[id].txiv[0] = *iv++;
394        wd->ap.staTable[id].txiv[1] = *iv++;
395        wd->ap.staTable[id].txiv[2] = *iv++;
396        wd->ap.staTable[id].txiv[3] = *iv;
397    }
398
399    zmw_leave_critical_section(dev);
400
401    return;
402}
403#endif //ZM_ENABLE_CENC
404
405
406/************************************************************************/
407/*                                                                      */
408/*    FUNCTION DESCRIPTION                  zfApFlushBufferedPsFrame    */
409/*      Free buffered PS frames.                                        */
410/*                                                                      */
411/*    INPUTS                                                            */
412/*      dev : device pointer                                            */
413/*                                                                      */
414/*    OUTPUTS                                                           */
415/*      None                                                            */
416/*                                                                      */
417/*    AUTHOR                                                            */
418/*      Stephen Chen        Atheros Communications, INC.    2007.1      */
419/*                                                                      */
420/************************************************************************/
421void zfApFlushBufferedPsFrame(zdev_t* dev)
422{
423    u16_t emptyFlag;
424    u16_t freeCount;
425    u16_t vap;
426    zbuf_t* psBuf = NULL;
427    zmw_get_wlan_dev(dev);
428    zmw_declare_for_critical_section();
429
430    freeCount = 0;
431    emptyFlag = 0;
432    while (1)
433    {
434        psBuf = NULL;
435        zmw_enter_critical_section(dev);
436        if (wd->ap.uniHead != wd->ap.uniTail)
437        {
438            psBuf = wd->ap.uniArray[wd->ap.uniHead];
439            wd->ap.uniHead = (wd->ap.uniHead + 1) & (ZM_UNI_ARRAY_SIZE - 1);
440        }
441        else
442        {
443            emptyFlag = 1;
444        }
445        zmw_leave_critical_section(dev);
446
447        if (psBuf != NULL)
448        {
449            zfwBufFree(dev, psBuf, ZM_ERR_FLUSH_PS_QUEUE);
450        }
451        zm_assert(freeCount++ < (ZM_UNI_ARRAY_SIZE*2));
452
453        if (emptyFlag != 0)
454        {
455            break;
456        }
457    }
458
459    for (vap=0; vap<ZM_MAX_AP_SUPPORT; vap++)
460    {
461        freeCount = 0;
462        emptyFlag = 0;
463        while (1)
464        {
465            psBuf = NULL;
466            zmw_enter_critical_section(dev);
467            if (wd->ap.bcmcHead[vap] != wd->ap.bcmcTail[vap])
468            {
469                psBuf = wd->ap.bcmcArray[vap][wd->ap.bcmcHead[vap]];
470                wd->ap.bcmcHead[vap] = (wd->ap.bcmcHead[vap] + 1)
471                        & (ZM_BCMC_ARRAY_SIZE - 1);
472            }
473            else
474            {
475                emptyFlag = 1;
476            }
477            zmw_leave_critical_section(dev);
478
479            if (psBuf != NULL)
480            {
481                zfwBufFree(dev, psBuf, ZM_ERR_FLUSH_PS_QUEUE);
482            }
483            zm_assert(freeCount++ < (ZM_BCMC_ARRAY_SIZE*2));
484
485            if (emptyFlag != 0)
486            {
487                break;
488            }
489        }
490    }
491    return;
492}
493
494
495u16_t zfApBufferPsFrame(zdev_t* dev, zbuf_t* buf, u16_t port)
496{
497    u16_t id;
498    u16_t addr[3];
499    u16_t vap = 0;
500    u8_t up;
501    u16_t fragOff;
502    u8_t ac;
503    u16_t ret;
504
505    zmw_get_wlan_dev(dev);
506
507    zmw_declare_for_critical_section();
508
509    if (port < ZM_MAX_AP_SUPPORT)
510    {
511        vap = port;
512    }
513
514    addr[0] = zmw_rx_buf_readh(dev, buf, 0);
515    addr[1] = zmw_rx_buf_readh(dev, buf, 2);
516    addr[2] = zmw_rx_buf_readh(dev, buf, 4);
517
518    if ((addr[0] & 0x1) == 0x1)
519    {
520        if (wd->ap.staPowerSaving > 0)
521        {
522            zmw_enter_critical_section(dev);
523
524            /* Buffer this BC or MC frame */
525            if (((wd->ap.bcmcTail[vap]+1)&(ZM_BCMC_ARRAY_SIZE-1))
526                    != wd->ap.bcmcHead[vap])
527            {
528                wd->ap.bcmcArray[vap][wd->ap.bcmcTail[vap]++] = buf;
529                wd->ap.bcmcTail[vap] &= (ZM_BCMC_ARRAY_SIZE-1);
530                zmw_leave_critical_section(dev);
531
532                zm_msg0_tx(ZM_LV_0, "Buffer BCMC");
533            }
534            else
535            {
536                /* bcmcArray full */
537                zmw_leave_critical_section(dev);
538
539                zm_msg0_tx(ZM_LV_0, "BCMC buffer full");
540
541                /* free buffer according to buffer type */
542                zfwBufFree(dev, buf, ZM_ERR_BCMC_PS_BUFFER_UNAVAILABLE);
543            }
544            return 1;
545        }
546    }
547    else
548    {
549        zmw_enter_critical_section(dev);
550
551        id = zfApFindSta(dev, addr);
552        if (id != 0xffff)
553        {
554            if (wd->ap.staTable[id].psMode == 1)
555            {
556
557                zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
558                ac = zcUpToAc[up&0x7] & 0x3;
559
560                if ((wd->ap.staTable[id].qosType == 1) &&
561                        ((wd->ap.staTable[id].qosInfo & (0x8>>ac)) != 0))
562                {
563                    ret = zfQueuePutNcs(dev, wd->ap.uapsdQ, buf, wd->tick);
564                    zmw_leave_critical_section(dev);
565                    if (ret != ZM_SUCCESS)
566                    {
567                        zfwBufFree(dev, buf, ZM_ERR_AP_UAPSD_QUEUE_FULL);
568                    }
569                }
570                else
571                {
572                /* Buffer this unicast frame */
573                if (((wd->ap.uniTail+1)&(ZM_UNI_ARRAY_SIZE-1))
574                        != wd->ap.uniHead)
575                {
576                    wd->ap.uniArray[wd->ap.uniTail++] = buf;
577                    wd->ap.uniTail &= (ZM_UNI_ARRAY_SIZE-1);
578                    zmw_leave_critical_section(dev);
579                    zm_msg0_tx(ZM_LV_0, "Buffer UNI");
580
581                }
582                else
583                {
584                    /* uniArray full */
585                    zmw_leave_critical_section(dev);
586                    zm_msg0_tx(ZM_LV_0, "UNI buffer full");
587                    /* free buffer according to buffer type */
588                    zfwBufFree(dev, buf, ZM_ERR_UNI_PS_BUFFER_UNAVAILABLE);
589                }
590                }
591                return 1;
592            } /* if (wd->ap.staTable[id++].psMode == 1) */
593        } /* if ((id = zfApFindSta(dev, addr)) != 0xffff) */
594        zmw_leave_critical_section(dev);
595    }
596
597    return 0;
598}
599
600u16_t zfApGetSTAInfoAndUpdatePs(zdev_t* dev, u16_t* addr, u16_t* state,
601                                u8_t* vap, u16_t psMode, u8_t* uapsdTrig)
602{
603    u16_t id;
604    u8_t uapsdStaAwake = 0;
605
606    zmw_get_wlan_dev(dev);
607
608    zmw_declare_for_critical_section();
609
610    zmw_enter_critical_section(dev);
611
612#ifdef ZM_AP_DEBUG
613    //psMode=0;
614#endif
615
616    id = zfApFindSta(dev, addr);
617    if (id != 0xffff)
618    {
619        if (psMode != 0)
620        {
621            zm_msg0_mm(ZM_LV_0, "psMode = 1");
622            if (wd->ap.staTable[id].psMode == 0)
623            {
624                wd->ap.staPowerSaving++;
625            }
626            else
627            {
628                if (wd->ap.staTable[id].qosType == 1)
629                {
630                    zm_msg0_mm(ZM_LV_0, "UAPSD trigger");
631                    *uapsdTrig = wd->ap.staTable[id].qosInfo;
632                }
633            }
634        }
635        else
636        {
637            if (wd->ap.staTable[id].psMode != 0)
638            {
639                wd->ap.staPowerSaving--;
640                if ((wd->ap.staTable[id].qosType == 1) && ((wd->ap.staTable[id].qosInfo&0xf)!=0))
641                {
642                    uapsdStaAwake = 1;
643                }
644            }
645        }
646
647        wd->ap.staTable[id].psMode = (u8_t) psMode;
648        wd->ap.staTable[id].time = wd->tick;
649        *vap = wd->ap.staTable[id].vap;
650        *state = wd->ap.staTable[id++].state;
651    }
652
653    zmw_leave_critical_section(dev);
654
655    if (uapsdStaAwake == 1)
656    {
657        zbuf_t* psBuf;
658        u8_t mb;
659
660        while (1)
661        {
662            psBuf = zfQueueGetWithMac(dev, wd->ap.uapsdQ, (u8_t*)addr, &mb);
663            if (psBuf != NULL)
664            {
665                zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
666            }
667            else
668            {
669                break;
670            }
671        }
672    }
673
674    return id;
675}
676
677/************************************************************************/
678/*                                                                      */
679/*    FUNCTION DESCRIPTION                  zfApGetNewSta               */
680/*      Get a new STA from station table.                               */
681/*                                                                      */
682/*    INPUTS                                                            */
683/*      dev : device pointer                                            */
684/*                                                                      */
685/*    OUTPUTS                                                           */
686/*      0xffff : fail                                                   */
687/*      other : STA table index                                         */
688/*                                                                      */
689/*    AUTHOR                                                            */
690/*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
691/*                                                                      */
692/************************************************************************/
693u16_t zfApGetNewSta(zdev_t* dev)
694{
695    u16_t i;
696
697    zmw_get_wlan_dev(dev);
698
699    for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
700    {
701        if (wd->ap.staTable[i].valid == 0)
702        {
703            zm_msg2_mm(ZM_LV_0, "zfApGetNewSta=", i);
704            return i;
705        }
706    }
707    return 0xffff;
708}
709
710
711/************************************************************************/
712/*                                                                      */
713/*    FUNCTION DESCRIPTION                  zfApAddSta                  */
714/*      Add a STA to station table.                                     */
715/*                                                                      */
716/*    INPUTS                                                            */
717/*      dev : device pointer                                            */
718/*      addr : STA MAC address                                          */
719/*      state : STA state                                               */
720/*      apId : Virtual AP ID                                            */
721/*      type : 0=>11b, 1=>11g                                           */
722/*                                                                      */
723/*    OUTPUTS                                                           */
724/*      0xffff : fail                                                   */
725/*      Other : index                                                   */
726/*                                                                      */
727/*    AUTHOR                                                            */
728/*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
729/*                                                                      */
730/************************************************************************/
731u16_t zfApAddSta(zdev_t* dev, u16_t* addr, u16_t state, u16_t apId, u8_t type,
732                 u8_t qosType, u8_t qosInfo)
733{
734    u16_t index;
735    u16_t i;
736
737    zmw_get_wlan_dev(dev);
738
739    zmw_declare_for_critical_section();
740
741    zm_msg1_mm(ZM_LV_0, "STA type=", type);
742
743    zmw_enter_critical_section(dev);
744
745    index = zfApFindSta(dev, addr);
746    if (index != 0xffff)
747    {
748        zm_msg0_mm(ZM_LV_2, "found");
749        /* Update STA state */
750        if ((state == ZM_STATE_AUTH) || (state == ZM_STATE_PREAUTH))
751        {
752            wd->ap.staTable[index].state = state;
753            wd->ap.staTable[index].time = wd->tick;
754            wd->ap.staTable[index].vap = (u8_t)apId;
755        }
756        else if (state == ZM_STATE_ASOC)
757        {
758            if ((wd->ap.staTable[index].state == ZM_STATE_AUTH))
759                    //&& (wd->ap.staTable[index].vap == apId))
760            {
761                wd->ap.staTable[index].state = state;
762                wd->ap.staTable[index].time = wd->tick;
763                wd->ap.staTable[index].qosType = qosType;
764                wd->ap.staTable[index].vap = (u8_t)apId;
765                wd->ap.staTable[index].staType = type;
766                wd->ap.staTable[index].qosInfo = qosInfo;
767
768                if (wd->frequency < 3000)
769                {
770                    /* Init 11b/g */
771                    zfRateCtrlInitCell(dev, &wd->ap.staTable[index].rcCell, type, 1, 1);
772                }
773                else
774                {
775                    /* Init 11a */
776                    zfRateCtrlInitCell(dev, &wd->ap.staTable[index].rcCell, type, 0, 1);
777                }
778
779                if (wd->zfcbApConnectNotify != NULL)
780                {
781                    wd->zfcbApConnectNotify(dev, (u8_t*)addr, apId);
782                }
783            }
784            else
785            {
786                index = 0xffff;
787            }
788        }
789    }
790    else
791    {
792        zm_msg0_mm(ZM_LV_2, "Not found");
793        if ((state == ZM_STATE_AUTH) || (state == ZM_STATE_PREAUTH))
794        {
795            /* Get a new STA and update state */
796            index = zfApGetNewSta(dev);
797            zm_msg2_mm(ZM_LV_1, "new STA index=", index);
798
799            if (index != 0xffff)
800            {
801                for (i=0; i<3; i++)
802                {
803                    wd->ap.staTable[index].addr[i] = addr[i];
804                }
805                wd->ap.staTable[index].state = state;
806                wd->ap.staTable[index].valid = 1;
807                wd->ap.staTable[index].time = wd->tick;
808                wd->ap.staTable[index].vap = (u8_t)apId;
809                wd->ap.staTable[index].encryMode = ZM_NO_WEP;
810            }
811        }
812    }
813
814    zmw_leave_critical_section(dev);
815
816    return index;
817}
818
819
820/************************************************************************/
821/*                                                                      */
822/*    FUNCTION DESCRIPTION                  zfApAgingSta                */
823/*      Aging STA in station table.                                     */
824/*                                                                      */
825/*    INPUTS                                                            */
826/*      dev : device pointer                                            */
827/*                                                                      */
828/*    OUTPUTS                                                           */
829/*      number of 11b STA in STA table                                  */
830/*                                                                      */
831/*    AUTHOR                                                            */
832/*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
833/*                                                                      */
834/************************************************************************/
835void zfApAgingSta(zdev_t* dev)
836{
837    u16_t i;
838    u32_t deltaMs;
839    u16_t addr[3];
840    u16_t txFlag;
841    u16_t psStaCount = 0;
842
843    zmw_get_wlan_dev(dev);
844
845    zmw_declare_for_critical_section();
846
847    wd->ap.gStaAssociated = wd->ap.bStaAssociated = 0;
848
849    for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
850    {
851        txFlag = 0;
852        zmw_enter_critical_section(dev);
853        if (wd->ap.staTable[i].valid == 1)
854        {
855            addr[0] = wd->ap.staTable[i].addr[0];
856            addr[1] = wd->ap.staTable[i].addr[1];
857            addr[2] = wd->ap.staTable[i].addr[2];
858            /* millisecond */
859            deltaMs = (u32_t)((u32_t)wd->tick-(u32_t)wd->ap.staTable[i].time)
860                      * ZM_MS_PER_TICK;
861
862            /* preauth */
863            if ((wd->ap.staTable[i].state == ZM_STATE_PREAUTH)
864                    && (deltaMs > ZM_PREAUTH_TIMEOUT_MS))
865            {
866                /* Aging STA */
867                wd->ap.staTable[i].valid = 0;
868                wd->ap.authSharing = 0;
869                txFlag = 1;
870            }
871
872            /* auth */
873            if ((wd->ap.staTable[i].state == ZM_STATE_AUTH)
874                    && (deltaMs > ZM_AUTH_TIMEOUT_MS))
875            {
876                /* Aging STA */
877                wd->ap.staTable[i].valid = 0;
878                txFlag = 1;
879            }
880
881            /* asoc */
882            if (wd->ap.staTable[i].state == ZM_STATE_ASOC)
883            {
884                if (wd->ap.staTable[i].psMode != 0)
885                {
886                    psStaCount++;
887                }
888
889                if (deltaMs > ((u32_t)wd->ap.staAgingTimeSec<<10))
890                {
891                    /* Aging STA */
892                    zm_msg1_mm(ZM_LV_0, "Age STA index=", i);
893                    wd->ap.staTable[i].valid = 0;
894                    txFlag = 1;
895                }
896                else if (deltaMs > ((u32_t)wd->ap.staProbingTimeSec<<10))
897                {
898                    if (wd->ap.staTable[i].psMode == 0)
899                    {
900                        /* Probing non-PS STA */
901                        zm_msg1_mm(ZM_LV_0, "Probing STA index=", i);
902                        wd->ap.staTable[i].time +=
903                                (wd->ap.staProbingTimeSec * ZM_TICK_PER_SECOND);
904                        txFlag = 2;
905                    }
906                }
907            }
908
909
910        }
911        zmw_leave_critical_section(dev);
912
913        if (txFlag == 1)
914        {
915            /* Send deauthentication management frame */
916            zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, addr, 4, 0, 0);
917        }
918        else if (txFlag == 2)
919        {
920            zfSendMmFrame(dev, ZM_WLAN_DATA_FRAME, addr, 0, 0, 0);
921        }
922
923    }
924
925    wd->ap.staPowerSaving = psStaCount;
926
927    return;
928}
929
930void zfApProtctionMonitor(zdev_t* dev)
931{
932    zmw_get_wlan_dev(dev);
933
934    /* 11b STA associated => nonErp, Protect */
935    if (wd->ap.bStaAssociated > 0)
936    {
937        /* Enable NonErp bit in information element */
938        wd->erpElement = ZM_WLAN_NON_ERP_PRESENT_BIT
939                         | ZM_WLAN_USE_PROTECTION_BIT;
940
941        /* Enable protection mode */
942        zfApSetProtectionMode(dev, 1);
943
944    }
945    /* 11b STA not associated, protection OBSS present => Protect */
946    else if (wd->ap.protectedObss > 2) //Threshold
947    {
948        if (wd->disableSelfCts == 0)
949        {
950            /* Disable NonErp bit in information element */
951            wd->erpElement = ZM_WLAN_USE_PROTECTION_BIT;
952
953            /* Enable protection mode */
954            zfApSetProtectionMode(dev, 1);
955        }
956    }
957    else
958    {
959        /* Disable NonErp bit in information element */
960        wd->erpElement = 0;
961
962        /* Disable protection mode */
963        zfApSetProtectionMode(dev, 0);
964    }
965    wd->ap.protectedObss = 0;
966}
967
968
969void zfApProcessBeacon(zdev_t* dev, zbuf_t* buf)
970{
971    u16_t offset;
972    u8_t ch;
973
974    zmw_get_wlan_dev(dev);
975
976    zm_msg0_mm(ZM_LV_3, "Rx beacon");
977
978    /* update Non-ERP flag(wd->ap.nonErpObss) */
979    offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP);
980    if (offset == 0xffff)
981    {
982        /* 11b OBSS */
983        wd->ap.protectedObss++;
984        return;
985    }
986
987    ch = zmw_rx_buf_readb(dev, buf, offset+2);
988    if ((ch & ZM_WLAN_USE_PROTECTION_BIT) == ZM_WLAN_USE_PROTECTION_BIT)
989    {
990        /* Protected OBSS */
991        wd->ap.protectedObss = 1;
992    }
993
994    return;
995}
996
997
998/************************************************************************/
999/*                                                                      */
1000/*    FUNCTION DESCRIPTION                  zfProcessAuth               */
1001/*      Process authenticate management frame.                          */
1002/*                                                                      */
1003/*    INPUTS                                                            */
1004/*      dev : device pointer                                            */
1005/*      buf : auth frame buffer                                         */
1006/*                                                                      */
1007/*    OUTPUTS                                                           */
1008/*      none                                                            */
1009/*                                                                      */
1010/*    AUTHOR                                                            */
1011/*      Stephen Chen        ZyDAS Technology Corporation    2005.10     */
1012/*                                                                      */
1013/************************************************************************/
1014/* Note : AP allows one authenticating STA at a time, does not          */
1015/*        support multiple authentication process. Make sure            */
1016/*        authentication state machine will not be blocked due          */
1017/*        to incompleted authentication handshake.                      */
1018void zfApProcessAuth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
1019{
1020    u16_t algo, seq, status;
1021    u8_t authSharing;
1022    u16_t ret;
1023    u16_t i;
1024    u8_t challengePassed = 0;
1025    u8_t frameCtrl;
1026    u32_t retAlgoSeq;
1027    u32_t retStatus;
1028    zmw_get_wlan_dev(dev);
1029    zmw_declare_for_critical_section();
1030
1031
1032    frameCtrl = zmw_rx_buf_readb(dev, buf, 1);
1033    /* AP : Auth share 3 */
1034    /* shift for WEP IV */
1035    if ((frameCtrl & 0x40) != 0)
1036    {
1037        algo = zmw_rx_buf_readh(dev, buf, 28);
1038        seq = zmw_rx_buf_readh(dev, buf, 30);
1039        status = zmw_rx_buf_readh(dev, buf, 32);
1040    }
1041    else
1042    {
1043        algo = zmw_rx_buf_readh(dev, buf, 24);
1044        seq = zmw_rx_buf_readh(dev, buf, 26);
1045        status = zmw_rx_buf_readh(dev, buf, 28);
1046    }
1047
1048    zm_msg2_mm(ZM_LV_0, "Rx Auth, seq=", seq);
1049
1050    /* Set default to authentication algorithm not support */
1051    retAlgoSeq = 0x20000 | algo;
1052    retStatus = 13; /* authentication algorithm not support */
1053
1054    /* AP : Auth open 1 */
1055    if (algo == 0)
1056    {
1057        if (wd->ap.authAlgo[apId] == 0)
1058        {
1059            retAlgoSeq = 0x20000;
1060            if (seq == 1)
1061            {
1062                /* AP : update STA to auth */
1063                ret = zfApAddSta(dev, src, ZM_STATE_AUTH, apId, 0, 0, 0);
1064                if (ret != 0xffff)
1065                {
1066                    /* AP : call zfwAuthNotify() for host to judge */
1067                    //zfwAuthNotify(dev, src);
1068
1069                    /* AP : response Auth seq=2, success */
1070                    retStatus = 0;
1071
1072                }
1073                else
1074                {
1075                    /* AP : response Auth seq=2, unspecific error */
1076                    retStatus = 1;
1077                }
1078            }
1079            else
1080            {
1081                /* AP : response Auth seq=2, sequence number out of expected */
1082                retStatus = 14;
1083            }
1084        }
1085    }
1086    /* AP : Auth share 1 */
1087    else if (algo == 1)
1088    {
1089        if (wd->ap.authAlgo[apId] == 1)
1090        {
1091            if (seq == 1)
1092            {
1093                retAlgoSeq = 0x20001;
1094
1095                /* critical section */
1096                zmw_enter_critical_section(dev);
1097                if (wd->ap.authSharing == 1)
1098                {
1099                    authSharing = 1;
1100                }
1101                else
1102                {
1103                    authSharing = 0;
1104                    wd->ap.authSharing = 1;
1105                }
1106                /* end of critical section */
1107                zmw_leave_critical_section(dev);
1108
1109                if (authSharing == 1)
1110                {
1111                    /* AP : response Auth seq=2, status = fail */
1112                    retStatus = 1;
1113                }
1114                else
1115                {
1116                    /* AP : update STA to preauth */
1117                    zfApAddSta(dev, src, ZM_STATE_PREAUTH, apId, 0, 0, 0);
1118
1119                    /* AP : call zfwAuthNotify() for host to judge */
1120                    //zfwAuthNotify(dev, src);
1121
1122                    /* AP : response Auth seq=2 */
1123                    retStatus = 0;
1124                }
1125            }
1126            else if (seq == 3)
1127            {
1128                retAlgoSeq = 0x40001;
1129
1130                if (wd->ap.authSharing == 1)
1131                {
1132                    /* check challenge text */
1133                    if (zmw_buf_readh(dev, buf, 30+4) == 0x8010)
1134                    {
1135                        for (i=0; i<128; i++)
1136                        {
1137                            if (wd->ap.challengeText[i]
1138                                        != zmw_buf_readb(dev, buf, 32+i+4))
1139                            {
1140                                break;
1141                            }
1142                        }
1143                        if (i == 128)
1144                        {
1145                            challengePassed = 1;
1146                        }
1147                    }
1148
1149                    if (challengePassed == 1)
1150                    {
1151                        /* AP : update STA to auth */
1152                        zfApAddSta(dev, src, ZM_STATE_AUTH, apId, 0, 0, 0);
1153
1154                        /* AP : response Auth seq=2 */
1155                        retStatus = 0;
1156                    }
1157                    else
1158                    {
1159                        /* AP : response Auth seq=2, challenge failure */
1160                        retStatus = 15;
1161
1162                        /* TODO : delete STA */
1163                    }
1164
1165                    wd->ap.authSharing = 0;
1166                }
1167            }
1168            else
1169            {
1170                retAlgoSeq = 0x40001;
1171                retStatus = 14;
1172            }
1173        }
1174    }
1175
1176    zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_AUTH, src, retAlgoSeq,
1177            retStatus, apId);
1178    return;
1179}
1180
1181void zfApProcessAsocReq(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
1182{
1183    u16_t aid = 0xffff;
1184    u8_t frameType;
1185    u16_t offset;
1186    u8_t staType = 0;
1187    u8_t qosType = 0;
1188    u8_t qosInfo = 0;
1189    u8_t tmp;
1190    u16_t i, j, k;
1191    u16_t encMode = 0;
1192
1193    zmw_get_wlan_dev(dev);
1194    /* AP : check SSID */
1195    offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID);
1196    if (offset != 0xffff)
1197    {
1198        k = 0;
1199        for (j = 0; j < wd->ap.vapNumber; j++)
1200        {
1201            tmp = zmw_buf_readb(dev, buf, offset+1);
1202            if (tmp
1203                        != wd->ap.ssidLen[j])
1204            {
1205                k++;
1206            }
1207        }
1208        if (k == wd->ap.vapNumber)
1209        {
1210            goto zlDeauth;
1211        }
1212
1213        k = 0;
1214        for (j = 0; j < wd->ap.vapNumber; j++)
1215        {
1216            for (i=0; i<wd->ap.ssidLen[j]; i++)
1217            {
1218                tmp = zmw_buf_readb(dev, buf, offset+2+i);
1219                if (tmp
1220                        != wd->ap.ssid[j][i])
1221                {
1222                    break;
1223                }
1224            }
1225            if (i == wd->ap.ssidLen[j])
1226            {
1227                apId = j;
1228            }
1229            else
1230            {
1231                k++;
1232            }
1233        }
1234        if (k == wd->ap.vapNumber)
1235        {
1236            goto zlDeauth;
1237        }
1238    }
1239
1240    /* TODO : check capability */
1241
1242    /* AP : check support rate */
1243    offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE);
1244    if (offset != 0xffff)
1245    {
1246        /* 11g STA */
1247        staType = 1;
1248    }
1249    //CWYang(+)
1250    offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY);
1251    if (offset != 0xffff)
1252    {
1253        /* 11n STA */
1254        staType = 2;
1255    }
1256
1257    /* TODO : do not allow 11b STA to associated in Pure G mode */
1258    if (wd->ap.wlanType[apId] == ZM_WLAN_TYPE_PURE_G && staType == 0)
1259    {
1260        zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 3, 0, 0);
1261        return;
1262    }
1263
1264    /* In pure B mode, we set G STA into B mode */
1265    if (wd->ap.wlanType[apId] == ZM_WLAN_TYPE_PURE_B && staType == 1)
1266    {
1267        staType = 0;
1268    }
1269
1270    /* AP : check 11i and WPA */
1271    /* AP : check 11h */
1272
1273    /* AP : check WME */
1274    offset = zfFindWifiElement(dev, buf, 2, 0);
1275    if (offset != 0xffff)
1276    {
1277        /* WME STA */
1278        qosType = 1;
1279        zm_msg0_mm(ZM_LV_0, "WME STA");
1280
1281        if (wd->ap.uapsdEnabled != 0)
1282        {
1283            qosInfo = zmw_rx_buf_readb(dev, buf, offset+8);
1284        }
1285    }
1286
1287    if (wd->ap.wpaSupport[apId] == 1)
1288    {
1289        offset = zfFindElement(dev, buf, ZM_WLAN_EID_WPA_IE);
1290        if (offset != 0xffff)
1291        {
1292            /* get WPA IE */
1293            u8_t length = zmw_rx_buf_readb(dev, buf, offset+1);
1294            if (length+2 < ZM_MAX_WPAIE_SIZE)
1295            {
1296                zfCopyFromRxBuffer(dev, buf, wd->ap.stawpaIe[apId], offset, length+2);
1297                wd->ap.stawpaLen[apId] = length+2;
1298                encMode = 1;
1299
1300
1301                zm_msg1_mm(ZM_LV_0, "WPA Mode zfwAsocNotify, apId=", apId);
1302
1303                /* AP : Call zfwAsocNotify() */
1304                if (wd->zfcbAsocNotify != NULL)
1305                {
1306                    wd->zfcbAsocNotify(dev, src, wd->ap.stawpaIe[apId], wd->ap.stawpaLen[apId], apId);
1307                }
1308            }
1309            else
1310            {
1311                goto zlDeauth;
1312            }
1313        }
1314        else if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_RSN_IE)) != 0xffff )
1315        {
1316            /* get RSN IE */
1317            u8_t length = zmw_rx_buf_readb(dev, buf, offset+1);
1318            if (length+2 < ZM_MAX_WPAIE_SIZE)
1319            {
1320                zfCopyFromRxBuffer(dev, buf, wd->ap.stawpaIe[apId], offset, length+2);
1321                wd->ap.stawpaLen[apId] = length+2;
1322                encMode = 1;
1323
1324                zm_msg1_mm(ZM_LV_0, "RSN Mode zfwAsocNotify, apId=", apId);
1325
1326                /* AP : Call zfwAsocNotify() */
1327                if (wd->zfcbAsocNotify != NULL)
1328                {
1329                    wd->zfcbAsocNotify(dev, src, wd->ap.stawpaIe[apId], wd->ap.stawpaLen[apId], apId);
1330                }
1331            }
1332            else
1333            {
1334                goto zlDeauth;
1335            }
1336        }
1337#ifdef ZM_ENABLE_CENC
1338        else if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CENC_IE)) != 0xffff )
1339        {
1340            /* get CENC IE */
1341            u8_t length = zmw_rx_buf_readb(dev, buf, offset+1);
1342
1343            if (length+2 < ZM_MAX_WPAIE_SIZE)
1344            {
1345                zfCopyFromRxBuffer(dev, buf, wd->ap.stawpaIe[apId], offset, length+2);
1346                wd->ap.stawpaLen[apId] = length+2;
1347                encMode = 1;
1348
1349                zm_msg1_mm(ZM_LV_0, "CENC Mode zfwAsocNotify, apId=", apId);
1350
1351                /* AP : Call zfwAsocNotify() */
1352                if (wd->zfcbCencAsocNotify != NULL)
1353                {
1354                    wd->zfcbCencAsocNotify(dev, src, wd->ap.stawpaIe[apId],
1355                            wd->ap.stawpaLen[apId], apId);
1356                }
1357            }
1358            else
1359            {
1360                goto zlDeauth;
1361            }
1362        }
1363#endif //ZM_ENABLE_CENC
1364        else
1365        {   /* ap is encryption but sta has no wpa/rsn ie */
1366            zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 6, 0, 0);
1367            return;
1368        }
1369    }
1370    /* sta has wpa/rsn ie but ap is no encryption */
1371    if ((wd->ap.wpaSupport[apId] == 0) && (encMode == 1))
1372    {
1373        zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 6, 0, 0);
1374        return;
1375    }
1376
1377    /* AP : update STA to asoc */
1378    aid = zfApAddSta(dev, src, ZM_STATE_ASOC, apId, staType, qosType, qosInfo);
1379
1380    zfApStoreAsocReqIe(dev, buf, aid);
1381
1382zlDeauth:
1383    /* AP : send asoc rsp2 */
1384    if (aid != 0xffff)
1385    {
1386        frameType = zmw_rx_buf_readb(dev, buf, 0);
1387
1388        if (frameType == ZM_WLAN_FRAME_TYPE_ASOCREQ)
1389        {
1390            zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ASOCRSP, src, 0, aid+1, apId);
1391        }
1392        else
1393        {
1394            zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_REASOCRSP, src, 0, aid+1, apId);
1395        }
1396    }
1397    else
1398    {
1399        /* TODO : send deauthentication */
1400        zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 6, 0, 0);
1401    }
1402
1403    return;
1404}
1405
1406void zfApStoreAsocReqIe(zdev_t* dev, zbuf_t* buf, u16_t aid)
1407{
1408    //struct zsWlanAssoFrameHeader* pAssoFrame;
1409    //u8_t  pBuf[sizeof(struct zsWlanAssoFrameHeader)];
1410    u16_t offset;
1411    u32_t i;
1412    u16_t length;
1413    u8_t  *htcap;
1414
1415    zmw_get_wlan_dev(dev);
1416
1417    for (i=0; i<wd->sta.asocRspFrameBodySize; i++)
1418    {
1419        wd->sta.asocRspFrameBody[i] = zmw_rx_buf_readb(dev, buf, i+24);
1420    }
1421    /* capability: 2 octets */
1422    offset = 24;
1423
1424    /* Listen interval: 2 octets */
1425    offset = 26;
1426
1427    /* SSID */
1428    offset = 28;
1429
1430    /* supported rates */
1431    offset = zfFindElement(dev, buf, ZM_WLAN_EID_SUPPORT_RATE);
1432    if (offset == 0xffff)
1433        return;
1434    length = zmw_rx_buf_readb(dev, buf, offset + 1);
1435
1436    /* extended supported rates */
1437    offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE);
1438    if (offset == 0xffff)
1439        return;
1440    length = zmw_rx_buf_readb(dev, buf, offset + 1);
1441
1442    /* power capability:4 octets */
1443    offset = offset + 2 + length;
1444
1445    /* supported channels: 4 octets */
1446    offset = offset + 2 + 4;
1447
1448    /* RSN */
1449
1450    /* QoS */
1451
1452    /* HT capabilities: 28 octets */
1453    offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY);
1454    if (offset != 0xffff) {
1455        /* atheros pre n */
1456        htcap = (u8_t *)&wd->ap.ie[aid].HtCap;
1457        htcap[0] = zmw_rx_buf_readb(dev, buf, offset);
1458        htcap[1] = 26;
1459        for (i=1; i<=26; i++)
1460        {
1461            htcap[i+1] = zmw_rx_buf_readb(dev, buf, offset + i);
1462            zm_debug_msg2("ASOC:  HT Capabilities, htcap=", htcap[i+1]);
1463        }
1464        return;
1465    }
1466    else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff) {
1467        /* pre n 2.0 standard */
1468        htcap = (u8_t *)&wd->ap.ie[aid].HtCap;
1469        for (i=0; i<28; i++)
1470        {
1471            htcap[i] = zmw_rx_buf_readb(dev, buf, offset + i);
1472            zm_debug_msg2("ASOC:  HT Capabilities, htcap=", htcap[i]);
1473        }
1474    }
1475    else {
1476        /* not 11n AP */
1477        return;
1478    }
1479
1480
1481    /* supported regulatory classes */
1482    offset = offset + length;
1483    //length = zmw_rx_buf_readb(dev, buf, offset + 1);
1484    {
1485    u8_t *htcap;
1486    htcap = (u8_t *)&wd->sta.ie.HtInfo;
1487    //zm_debug_msg2("ASOC:  HT Capabilities info=", ((u16_t *)htcap)[1]);
1488    //zm_debug_msg2("ASOC:  A-MPDU parameters=", htcap[4]);
1489    //zm_debug_msg2("ASOC:  Supported MCS set=", ((u32_t *)htcap)[1]>>8);
1490    }
1491
1492}
1493
1494void zfApProcessAsocRsp(zdev_t* dev, zbuf_t* buf)
1495{
1496
1497}
1498
1499void zfApProcessDeauth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
1500{
1501    u16_t aid;
1502    zmw_get_wlan_dev(dev);
1503    zmw_declare_for_critical_section();
1504
1505    zmw_enter_critical_section(dev);
1506    /* AP : if SA=associated STA then deauthenticate STA */
1507    aid = zfApFindSta(dev, src);
1508    if (aid != 0xffff)
1509    {
1510        /* Clear STA table */
1511        wd->ap.staTable[aid].valid = 0;
1512        if (wd->zfcbDisAsocNotify != NULL)
1513        {
1514            wd->zfcbDisAsocNotify(dev, (u8_t*)src, apId);
1515        }
1516    }
1517    zmw_leave_critical_section(dev);
1518
1519}
1520
1521void zfApProcessDisasoc(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
1522{
1523    u16_t aid;
1524    zmw_get_wlan_dev(dev);
1525    zmw_declare_for_critical_section();
1526
1527    zmw_enter_critical_section(dev);
1528    /* AP : if SA=associated STA then deauthenticate STA */
1529    aid = zfApFindSta(dev, src);
1530    if (aid != 0xffff)
1531    {
1532        /* Clear STA table */
1533        wd->ap.staTable[aid].valid = 0;
1534        zmw_leave_critical_section(dev);
1535        if (wd->zfcbDisAsocNotify != NULL)
1536        {
1537            wd->zfcbDisAsocNotify(dev, (u8_t*)src, apId);
1538        }
1539    }
1540    zmw_leave_critical_section(dev);
1541
1542}
1543
1544
1545void zfApProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo)
1546{
1547}
1548
1549/************************************************************************/
1550/*                                                                      */
1551/*    FUNCTION DESCRIPTION                  zfApAddIeSsid               */
1552/*      Add AP information element SSID to buffer.                      */
1553/*                                                                      */
1554/*    INPUTS                                                            */
1555/*      dev : device pointer                                            */
1556/*      buf : buffer to add information element                         */
1557/*      offset : add information element from this offset               */
1558/*      vap : virtual AP ID                                             */
1559/*                                                                      */
1560/*    OUTPUTS                                                           */
1561/*      buffer offset after adding information element                  */
1562/*                                                                      */
1563/*    AUTHOR                                                            */
1564/*      Stephen Chen        ZyDAS Technology Corporation    2005.11     */
1565/*                                                                      */
1566/************************************************************************/
1567u16_t zfApAddIeSsid(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
1568{
1569    u16_t i;
1570
1571    zmw_get_wlan_dev(dev);
1572
1573    /* Element ID */
1574    zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
1575
1576    /* Element Length */
1577    zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.ssidLen[vap]);
1578
1579    /* Information : SSID */
1580    for (i=0; i<wd->ap.ssidLen[vap]; i++)
1581    {
1582        zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.ssid[vap][i]);
1583    }
1584
1585    return offset;
1586}
1587
1588
1589/************************************************************************/
1590/*                                                                      */
1591/*    FUNCTION DESCRIPTION                  zfApAddIeTim                */
1592/*      Add AP information element TIM to buffer.                       */
1593/*                                                                      */
1594/*    INPUTS                                                            */
1595/*      dev : device pointer                                            */
1596/*      buf : buffer to add information element                         */
1597/*      offset : add information element from this offset               */
1598/*      vap : virtual AP ID                                             */
1599/*                                                                      */
1600/*    OUTPUTS                                                           */
1601/*      buffer offset after adding information element                  */
1602/*                                                                      */
1603/*    AUTHOR                                                            */
1604/*      Stephen Chen        ZyDAS Technology Corporation    2005.11     */
1605/*                                                                      */
1606/************************************************************************/
1607u16_t zfApAddIeTim(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
1608{
1609    u8_t uniBitMap[9];
1610    u16_t highestByte;
1611    u16_t i;
1612    u16_t lenOffset;
1613    u16_t id;
1614    u16_t dst[3];
1615    u16_t aid;
1616    u16_t bitPosition;
1617    u16_t bytePosition;
1618    zbuf_t* psBuf;
1619    zbuf_t* tmpBufArray[ZM_UNI_ARRAY_SIZE];
1620    u16_t tmpBufArraySize = 0;
1621
1622    zmw_get_wlan_dev(dev);
1623
1624    zmw_declare_for_critical_section();
1625
1626    /* Element ID */
1627    zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_TIM);
1628
1629    /* offset of Element Length */
1630    lenOffset = offset++;
1631
1632    /* Information : TIM */
1633    /* DTIM count */
1634    /* TODO : Doesn't work for Virtual AP's case */
1635    wd->CurrentDtimCount++;
1636    if (wd->CurrentDtimCount >= wd->dtim)
1637    {
1638        wd->CurrentDtimCount = 0;
1639    }
1640    zmw_tx_buf_writeb(dev, buf, offset++, wd->CurrentDtimCount);
1641    /* DTIM period */
1642    zmw_tx_buf_writeb(dev, buf, offset++, wd->dtim);
1643    /* bitmap offset */
1644    zmw_tx_buf_writeb(dev, buf, offset++, 0);
1645
1646    /* Update BCMC bit */
1647    if (wd->CurrentDtimCount == 0)
1648    {
1649        zmw_enter_critical_section(dev);
1650        wd->ap.timBcmcBit[vap] = (wd->ap.bcmcTail[vap]!=wd->ap.bcmcHead[vap])?1:0;
1651        zmw_leave_critical_section(dev);
1652    }
1653    else
1654    {
1655        wd->ap.timBcmcBit[vap] = 0;
1656    }
1657
1658    /* Update Unicast bitmap */
1659    /* reset bit map */
1660    for (i=0; i<9; i++)
1661    {
1662        uniBitMap[i] = 0;
1663    }
1664    highestByte = 0;
1665
1666    zmw_enter_critical_section(dev);
1667
1668    id = wd->ap.uniHead;
1669    while (id != wd->ap.uniTail)
1670    {
1671        psBuf = wd->ap.uniArray[id];
1672
1673        /* TODO : Aging PS frame after queuing for more than 10 seconds */
1674
1675        /* get destination STA's aid */
1676        dst[0] = zmw_tx_buf_readh(dev, psBuf, 0);
1677        dst[1] = zmw_tx_buf_readh(dev, psBuf, 2);
1678        dst[2] = zmw_tx_buf_readh(dev, psBuf, 4);
1679        aid = zfApFindSta(dev, dst);
1680        if (aid != 0xffff)
1681        {
1682            if (wd->ap.staTable[aid].psMode != 0)
1683            {
1684                zm_msg1_mm(ZM_LV_0, "aid=",aid);
1685                aid++;
1686                zm_assert(aid<=64);
1687                bitPosition = (1 << (aid & 0x7));
1688                bytePosition = (aid >> 3);
1689                uniBitMap[bytePosition] |= bitPosition;
1690
1691                if (bytePosition>highestByte)
1692                {
1693                    highestByte = bytePosition;
1694                }
1695                id = (id+1) & (ZM_UNI_ARRAY_SIZE-1);
1696            }
1697            else
1698            {
1699                zm_msg0_mm(ZM_LV_0, "Send PS frame which STA no longer in PS mode");
1700                /* Send PS frame which STA no longer in PS mode */
1701                zfApRemoveFromPsQueue(dev, id, dst);
1702                tmpBufArray[tmpBufArraySize++] = psBuf;
1703            }
1704        }
1705        else
1706        {
1707            zm_msg0_mm(ZM_LV_0, "Free garbage PS frame");
1708            /* Free garbage PS frame */
1709            zfApRemoveFromPsQueue(dev, id, dst);
1710            zfwBufFree(dev, psBuf, 0);
1711        }
1712    }
1713
1714    zmw_leave_critical_section(dev);
1715
1716    zfQueueGenerateUapsdTim(dev, wd->ap.uapsdQ, uniBitMap, &highestByte);
1717
1718    zm_msg1_mm(ZM_LV_3, "bm=",uniBitMap[0]);
1719    zm_msg1_mm(ZM_LV_3, "highestByte=",highestByte);
1720    zm_msg1_mm(ZM_LV_3, "timBcmcBit[]=",wd->ap.timBcmcBit[vap]);
1721
1722    /* bitmap */
1723    zmw_tx_buf_writeb(dev, buf, offset++,
1724                         uniBitMap[0] | wd->ap.timBcmcBit[vap]);
1725    for (i=0; i<highestByte; i++)
1726    {
1727        zmw_tx_buf_writeb(dev, buf, offset++, uniBitMap[i+1]);
1728    }
1729
1730    /* Element Length */
1731    zmw_tx_buf_writeb(dev, buf, lenOffset, highestByte+4);
1732
1733    for (i=0; i<tmpBufArraySize; i++)
1734    {
1735        /* Put to VTXQ[ac] */
1736        zfPutVtxq(dev, tmpBufArray[i]);
1737    }
1738    /* Push VTXQ[ac] */
1739    zfPushVtxq(dev);
1740
1741    return offset;
1742}
1743
1744
1745
1746/************************************************************************/
1747/*                                                                      */
1748/*    FUNCTION DESCRIPTION                  zfApRemoveFromPsQueue       */
1749/*      Remove zbuf from PS queue.                                      */
1750/*                                                                      */
1751/*    INPUTS                                                            */
1752/*      dev : device pointer                                            */
1753/*      id : index in ps queue                                          */
1754/*                                                                      */
1755/*    OUTPUTS                                                           */
1756/*      more data bit                                                   */
1757/*                                                                      */
1758/*    AUTHOR                                                            */
1759/*      Stephen Chen        Atheros Communications, INC.    2007.1      */
1760/*                                                                      */
1761/************************************************************************/
1762u8_t zfApRemoveFromPsQueue(zdev_t* dev, u16_t id, u16_t* addr)
1763{
1764    u16_t dst[3];
1765    u16_t nid;
1766    u8_t moreData = 0;
1767    zmw_get_wlan_dev(dev);
1768
1769    wd->ap.uniTail = (wd->ap.uniTail-1) & (ZM_UNI_ARRAY_SIZE-1);
1770    while (id != wd->ap.uniTail)
1771    {
1772        nid = (id + 1) & (ZM_UNI_ARRAY_SIZE - 1);
1773        wd->ap.uniArray[id] = wd->ap.uniArray[nid];
1774
1775        /* Search until tail to config more data bit */
1776        dst[0] = zmw_buf_readh(dev, wd->ap.uniArray[id], 0);
1777        dst[1] = zmw_buf_readh(dev, wd->ap.uniArray[id], 2);
1778        dst[2] = zmw_buf_readh(dev, wd->ap.uniArray[id], 4);
1779        if ((addr[0] == dst[0]) && (addr[1] == dst[1])
1780                && (addr[2] == dst[2]))
1781        {
1782            moreData = 0x20;
1783        }
1784
1785        id = nid;
1786    }
1787    return moreData;
1788}
1789
1790/************************************************************************/
1791/*                                                                      */
1792/*    FUNCTION DESCRIPTION                  zfApAddIeWmePara            */
1793/*      Add WME Parameter Element to buffer.                            */
1794/*                                                                      */
1795/*    INPUTS                                                            */
1796/*      dev : device pointer                                            */
1797/*      buf : buffer to add information element                         */
1798/*      offset : add information element from this offset               */
1799/*      vap : virtual AP ID                                             */
1800/*                                                                      */
1801/*    OUTPUTS                                                           */
1802/*      buffer offset after adding information element                  */
1803/*                                                                      */
1804/*    AUTHOR                                                            */
1805/*      Stephen Chen        ZyDAS Technology Corporation    2006.1      */
1806/*                                                                      */
1807/************************************************************************/
1808u16_t zfApAddIeWmePara(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
1809{
1810    zmw_get_wlan_dev(dev);
1811
1812    /* Element ID */
1813    zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WIFI_IE);
1814
1815    /* Element Length */
1816    zmw_tx_buf_writeb(dev, buf, offset++, 24);
1817
1818    /* OUI */
1819    zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1820    zmw_tx_buf_writeb(dev, buf, offset++, 0x50);
1821    zmw_tx_buf_writeb(dev, buf, offset++, 0xF2);
1822    zmw_tx_buf_writeb(dev, buf, offset++, 0x02);
1823    zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
1824    zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
1825
1826    /* QoS Info */
1827    if (wd->ap.uapsdEnabled)
1828    {
1829        zmw_tx_buf_writeb(dev, buf, offset++, 0x81);
1830    }
1831    else
1832    {
1833    zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
1834    }
1835
1836    /* Reserved */
1837    zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1838
1839    /* Best Effort AC parameters */
1840    zmw_tx_buf_writeb(dev, buf, offset++, 0x03);
1841    zmw_tx_buf_writeb(dev, buf, offset++, 0xA4);
1842    zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1843    zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1844    /* Backfround AC parameters */
1845    zmw_tx_buf_writeb(dev, buf, offset++, 0x27);
1846    zmw_tx_buf_writeb(dev, buf, offset++, 0xA4);
1847    zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1848    zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1849    /* Video AC parameters */
1850    zmw_tx_buf_writeb(dev, buf, offset++, 0x42);
1851    zmw_tx_buf_writeb(dev, buf, offset++, 0x43);
1852    zmw_tx_buf_writeb(dev, buf, offset++, 0x5E);
1853    zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1854    /* Voice AC parameters */
1855    zmw_tx_buf_writeb(dev, buf, offset++, 0x62);
1856    zmw_tx_buf_writeb(dev, buf, offset++, 0x32);
1857    zmw_tx_buf_writeb(dev, buf, offset++, 0x2F);
1858    zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1859
1860    return offset;
1861}
1862
1863
1864/************************************************************************/
1865/*                                                                      */
1866/*    FUNCTION DESCRIPTION                  zfApSendBeacon              */
1867/*      Sned AP mode beacon.                                            */
1868/*                                                                      */
1869/*    INPUTS                                                            */
1870/*      dev : device pointer                                            */
1871/*                                                                      */
1872/*    OUTPUTS                                                           */
1873/*      none                                                            */
1874/*                                                                      */
1875/*    AUTHOR                                                            */
1876/*      Stephen Chen        ZyDAS Technology Corporation    2005.11     */
1877/*                                                                      */
1878/************************************************************************/
1879void zfApSendBeacon(zdev_t* dev)
1880{
1881    zbuf_t* buf;
1882    u16_t offset;
1883    u16_t vap;
1884    u16_t seq;
1885
1886    zmw_get_wlan_dev(dev);
1887
1888    zmw_declare_for_critical_section();
1889
1890    wd->ap.beaconCounter++;
1891    if (wd->ap.beaconCounter >= wd->ap.vapNumber)
1892    {
1893        wd->ap.beaconCounter = 0;
1894    }
1895    vap = wd->ap.beaconCounter;
1896
1897
1898    zm_msg1_mm(ZM_LV_2, "Send beacon, vap=", vap);
1899
1900    /* TBD : Maximum size of beacon */
1901    buf = zfwBufAllocate(dev, 1024);
1902    if (buf == NULL)
1903    {
1904        zm_msg0_mm(ZM_LV_0, "Alloc beacon buf Fail!");
1905        return;
1906    }
1907
1908    offset = 0;
1909
1910    /* wlan header */
1911    /* Frame control */
1912    zmw_tx_buf_writeh(dev, buf, offset, 0x0080);
1913    offset+=2;
1914    /* Duration */
1915    zmw_tx_buf_writeh(dev, buf, offset, 0x0000);
1916    offset+=2;
1917    /* Address 1 */
1918    zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
1919    offset+=2;
1920    zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
1921    offset+=2;
1922    zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
1923    offset+=2;
1924    /* Address 2 */
1925    zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
1926    offset+=2;
1927    zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
1928    offset+=2;
1929#ifdef ZM_VAPMODE_MULTILE_SSID
1930    zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]); //Multiple SSID
1931#else
1932    zmw_tx_buf_writeh(dev, buf, offset, (wd->macAddr[2]+(vap<<8))); //VAP
1933#endif
1934    offset+=2;
1935    /* Address 3 */
1936    zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
1937    offset+=2;
1938    zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
1939    offset+=2;
1940#ifdef ZM_VAPMODE_MULTILE_SSID
1941    zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]); //Multiple SSID
1942#else
1943    zmw_tx_buf_writeh(dev, buf, offset, (wd->macAddr[2]+(vap<<8))); //VAP
1944#endif
1945    offset+=2;
1946
1947    /* Sequence number */
1948    zmw_enter_critical_section(dev);
1949    seq = ((wd->mmseq++)<<4);
1950    zmw_leave_critical_section(dev);
1951    zmw_tx_buf_writeh(dev, buf, offset, seq);
1952    offset+=2;
1953
1954    /* 24-31 Time Stamp : hardware will fill this field */
1955    zmw_tx_buf_writeh(dev, buf, offset, 0);
1956    zmw_tx_buf_writeh(dev, buf, offset+2, 0);
1957    zmw_tx_buf_writeh(dev, buf, offset+4, 0);
1958    zmw_tx_buf_writeh(dev, buf, offset+6, 0);
1959    offset+=8;
1960
1961    /* Beacon Interval */
1962    zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval);
1963    offset+=2;
1964
1965    /* Capability */
1966    zmw_tx_buf_writeh(dev, buf, offset, wd->ap.capab[vap]);
1967    offset+=2;
1968
1969    /* SSID */
1970    if (wd->ap.hideSsid[vap] == 0)
1971    {
1972        offset = zfApAddIeSsid(dev, buf, offset, vap);
1973    }
1974    else
1975    {
1976        zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
1977        zmw_tx_buf_writeb(dev, buf, offset++, 0);
1978
1979    }
1980
1981    /* Support Rate */
1982    if ( wd->frequency < 3000 )
1983    {
1984    offset = zfMmAddIeSupportRate(dev, buf, offset,
1985                                  ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
1986    }
1987    else
1988    {
1989        offset = zfMmAddIeSupportRate(dev, buf, offset,
1990                                  ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
1991    }
1992
1993    /* DS parameter set */
1994    offset = zfMmAddIeDs(dev, buf, offset);
1995
1996    /* TIM */
1997    offset = zfApAddIeTim(dev, buf, offset, vap);
1998
1999    /* If WLAN Type is not PURE B */
2000    if (wd->ap.wlanType[vap] != ZM_WLAN_TYPE_PURE_B)
2001    {
2002        if ( wd->frequency < 3000 )
2003        {
2004        /* ERP Information */
2005        offset = zfMmAddIeErp(dev, buf, offset);
2006
2007        /* Extended Supported Rates */
2008        offset = zfMmAddIeSupportRate(dev, buf, offset,
2009                                      ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
2010    }
2011    }
2012
2013    /* TODO : country information */
2014    /* TODO : RSN */
2015    if (wd->ap.wpaSupport[vap] == 1)
2016    {
2017        offset = zfMmAddIeWpa(dev, buf, offset, vap);
2018    }
2019
2020    /* WME Parameters */
2021    if (wd->ap.qosMode == 1)
2022    {
2023        offset = zfApAddIeWmePara(dev, buf, offset, vap);
2024    }
2025
2026    /* HT Capabilities Info */
2027    offset = zfMmAddHTCapability(dev, buf, offset);
2028
2029    /* Extended HT Capabilities Info */
2030    offset = zfMmAddExtendedHTCapability(dev, buf, offset);
2031
2032    /* 1212 : write to beacon fifo */
2033    /* 1221 : write to share memory */
2034    zfHpSendBeacon(dev, buf, offset);
2035
2036    /* Free beacon buffer */
2037    /* TODO: In order to fit the madwifi beacon architecture, we need to
2038       free beacon buffer in the HAL layer.
2039     */
2040
2041    //zfwBufFree(dev, buf, 0);
2042}
2043
2044
2045/************************************************************************/
2046/*                                                                      */
2047/*    FUNCTION DESCRIPTION                  zfIntrabssForward           */
2048/*      Called to transmit intra-BSS frame from upper layer.            */
2049/*                                                                      */
2050/*    INPUTS                                                            */
2051/*      dev : device pointer                                            */
2052/*      buf : buffer pointer                                            */
2053/*      vap : virtual AP                                                */
2054/*                                                                      */
2055/*    OUTPUTS                                                           */
2056/*      1 : unicast intras-BSS frame                                    */
2057/*      0 : other frames                                                */
2058/*                                                                      */
2059/*    AUTHOR                                                            */
2060/*      Stephen             ZyDAS Technology Corporation    2005.11     */
2061/*                                                                      */
2062/************************************************************************/
2063u16_t zfIntrabssForward(zdev_t* dev, zbuf_t* buf, u8_t srcVap)
2064{
2065    u16_t err;
2066    u16_t asocFlag = 0;
2067    u16_t dst[3];
2068    u16_t aid;
2069    u16_t staState;
2070    zbuf_t* txBuf;
2071    u16_t len;
2072    u16_t i;
2073    u16_t temp;
2074    u16_t ret;
2075    u8_t vap = 0;
2076#ifdef ZM_ENABLE_NATIVE_WIFI
2077    dst[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
2078    dst[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
2079    dst[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
2080#else
2081    dst[0] = zmw_rx_buf_readh(dev, buf, 0);
2082    dst[1] = zmw_rx_buf_readh(dev, buf, 2);
2083    dst[2] = zmw_rx_buf_readh(dev, buf, 4);
2084#endif  // ZM_ENABLE_NATIVE_WIFI
2085
2086    /* Do Intra-BSS forward(data copy) if necessary*/
2087    if ((dst[0]&0x1) != 0x1)
2088    {
2089        aid = zfApGetSTAInfo(dev, dst, &staState, &vap);
2090        if ((aid != 0xffff) && (staState == ZM_STATE_ASOC) && (srcVap == vap))
2091        {
2092            asocFlag = 1;
2093            zm_msg0_rx(ZM_LV_2, "Intra-BSS forward : asoc STA");
2094        }
2095
2096    }
2097    else
2098    {
2099        vap = srcVap;
2100        zm_msg0_rx(ZM_LV_2, "Intra-BSS forward : BCorMC");
2101    }
2102
2103    /* destination address = associated STA or BC/MC */
2104    if ((asocFlag == 1) || ((dst[0]&0x1) == 0x1))
2105    {
2106        /* Allocate frame */
2107        txBuf = zfwBufAllocate(dev, ZM_RX_FRAME_SIZE);
2108        if (txBuf == NULL)
2109        {
2110            zm_msg0_rx(ZM_LV_1, "Alloc intra-bss buf Fail!");
2111            goto zlAllocError;
2112        }
2113
2114        /* Copy frame */
2115        len = zfwBufGetSize(dev, buf);
2116        for (i=0; i<len; i+=2)
2117        {
2118            temp = zmw_rx_buf_readh(dev, buf, i);
2119            zmw_tx_buf_writeh(dev, txBuf, i, temp);
2120        }
2121        zfwBufSetSize(dev, txBuf, len);
2122
2123#ifdef ZM_ENABLE_NATIVE_WIFI
2124        /* Tx-A2 = Rx-A1, Tx-A3 = Rx-A2, Tx-A1 = Rx-A3 */
2125        for (i=0; i<6; i+=2)
2126        {
2127            temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+i);
2128            zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A2_OFFSET+i, temp);
2129            temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+i);
2130            zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A3_OFFSET+i, temp);
2131            temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+i);
2132            zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A1_OFFSET+i, temp);
2133        }
2134
2135        #endif
2136
2137        /* Transmit frame */
2138        /* Return error if port is disabled */
2139        err = zfTxPortControl(dev, txBuf, vap);
2140        if (err == ZM_PORT_DISABLED)
2141        {
2142            err = ZM_ERR_TX_PORT_DISABLED;
2143            goto zlTxError;
2144        }
2145
2146        /* AP : Buffer frame for power saving STA */
2147        ret = zfApBufferPsFrame(dev, txBuf, vap);
2148        if (ret == 0)
2149        {
2150            /* forward frame if not been buffered */
2151            /* Put to VTXQ[ac] */
2152            ret = zfPutVtxq(dev, txBuf);
2153            /* Push VTXQ[ac] */
2154            zfPushVtxq(dev);
2155
2156        }
2157    }
2158    return asocFlag;
2159
2160zlTxError:
2161    zfwBufFree(dev, txBuf, 0);
2162zlAllocError:
2163    return asocFlag;
2164}
2165
2166struct zsMicVar* zfApGetRxMicKey(zdev_t* dev, zbuf_t* buf)
2167{
2168    u8_t sa[6];
2169    u16_t id = 0, macAddr[3];
2170
2171    zmw_get_wlan_dev(dev);
2172
2173    zfCopyFromRxBuffer(dev, buf, sa, ZM_WLAN_HEADER_A2_OFFSET, 6);
2174
2175    macAddr[0] = sa[0] + (sa[1] << 8);
2176    macAddr[1] = sa[2] + (sa[3] << 8);
2177    macAddr[2] = sa[4] + (sa[5] << 8);
2178
2179    id = zfApFindSta(dev, macAddr);
2180    if (id != 0xffff)
2181        return (&wd->ap.staTable[id].rxMicKey);
2182
2183    return NULL;
2184}
2185
2186struct zsMicVar* zfApGetTxMicKey(zdev_t* dev, zbuf_t* buf, u8_t* qosType)
2187{
2188    u8_t da[6];
2189    u16_t id = 0, macAddr[3];
2190
2191    zmw_get_wlan_dev(dev);
2192
2193    zfCopyFromIntTxBuffer(dev, buf, da, 0, 6);
2194
2195    macAddr[0] = da[0] + (da[1] << 8);
2196    macAddr[1] = da[2] + (da[3] << 8);
2197    macAddr[2] = da[4] + (da[5] << 8);
2198
2199    if ((macAddr[0] & 0x1))
2200    {
2201        return (&wd->ap.bcMicKey[0]);
2202    }
2203    else if ((id = zfApFindSta(dev, macAddr)) != 0xffff)
2204    {
2205        *qosType = wd->ap.staTable[id].qosType;
2206        return (&wd->ap.staTable[id].txMicKey);
2207    }
2208
2209    return NULL;
2210}
2211
2212u16_t zfApUpdatePsBit(zdev_t* dev, zbuf_t* buf, u8_t* vap, u8_t* uapsdTrig)
2213{
2214    u16_t staState;
2215    u16_t aid;
2216    u16_t psBit;
2217    u16_t src[3];
2218    u16_t dst[1];
2219    u16_t i;
2220
2221    zmw_get_wlan_dev(dev);
2222
2223    src[0] = zmw_rx_buf_readh(dev, buf, 10);
2224    src[1] = zmw_rx_buf_readh(dev, buf, 12);
2225    src[2] = zmw_rx_buf_readh(dev, buf, 14);
2226
2227    if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3)
2228    {
2229        /* AP */
2230        dst[0] = zmw_rx_buf_readh(dev, buf, 4);
2231
2232        psBit = (zmw_rx_buf_readb(dev, buf, 1) & 0x10) >> 4;
2233        /* Get AID and update STA PS mode */
2234        aid = zfApGetSTAInfoAndUpdatePs(dev, src, &staState, vap, psBit, uapsdTrig);
2235
2236        /* if STA not associated, send deauth */
2237        if ((aid == 0xffff) || (staState != ZM_STATE_ASOC))
2238        {
2239            if ((dst[0]&0x1)==0)
2240            {
2241                zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 0x7,
2242                        0, 0);
2243            }
2244
2245            return ZM_ERR_STA_NOT_ASSOCIATED;
2246        }
2247    } /* if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3) */
2248    else
2249    {
2250        /* WDS */
2251        for (i=0; i<ZM_MAX_WDS_SUPPORT; i++)
2252        {
2253            if ((wd->ap.wds.wdsBitmap & (1<<i)) != 0)
2254            {
2255                if ((src[0] == wd->ap.wds.macAddr[i][0])
2256                        && (src[1] == wd->ap.wds.macAddr[i][1])
2257                        && (src[2] == wd->ap.wds.macAddr[i][2]))
2258                {
2259                    *vap = 0x20 + i;
2260                    break;
2261                }
2262            }
2263        }
2264    }
2265    return ZM_SUCCESS;
2266}
2267
2268void zfApProcessPsPoll(zdev_t* dev, zbuf_t* buf)
2269{
2270    u16_t src[3];
2271    u16_t dst[3];
2272    zbuf_t* psBuf = NULL;
2273    u16_t id;
2274    u8_t moreData = 0;
2275
2276    zmw_get_wlan_dev(dev);
2277
2278    zmw_declare_for_critical_section();
2279
2280    src[0] = zmw_tx_buf_readh(dev, buf, 10);
2281    src[1] = zmw_tx_buf_readh(dev, buf, 12);
2282    src[2] = zmw_tx_buf_readh(dev, buf, 14);
2283
2284    /* Find ps buffer for PsPoll */
2285    zmw_enter_critical_section(dev);
2286    id = wd->ap.uniHead;
2287    while (id != wd->ap.uniTail)
2288    {
2289        psBuf = wd->ap.uniArray[id];
2290
2291        dst[0] = zmw_tx_buf_readh(dev, psBuf, 0);
2292        dst[1] = zmw_tx_buf_readh(dev, psBuf, 2);
2293        dst[2] = zmw_tx_buf_readh(dev, psBuf, 4);
2294
2295        if ((src[0] == dst[0]) && (src[1] == dst[1]) && (src[2] == dst[2]))
2296        {
2297            moreData = zfApRemoveFromPsQueue(dev, id, src);
2298            break;
2299        }
2300        else
2301        {
2302            psBuf = NULL;
2303        }
2304        id = (id + 1) & (ZM_UNI_ARRAY_SIZE - 1);
2305    }
2306    zmw_leave_critical_section(dev);
2307
2308    /* Send ps buffer */
2309    if (psBuf != NULL)
2310    {
2311        /* Send with more data bit */
2312        zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, moreData);
2313    }
2314
2315    return;
2316}
2317
2318void zfApSetProtectionMode(zdev_t* dev, u16_t mode)
2319{
2320    zmw_get_wlan_dev(dev);
2321
2322    if (mode == 0)
2323    {
2324        if (wd->ap.protectionMode != mode)
2325        {
2326            /* Write MAC&PHY registers to disable protection */
2327
2328            wd->ap.protectionMode = mode;
2329        }
2330
2331    }
2332    else
2333    {
2334        if (wd->ap.protectionMode != mode)
2335        {
2336            /* Write MAC&PHY registers to enable protection */
2337
2338            wd->ap.protectionMode = mode;
2339        }
2340    }
2341    return;
2342}
2343
2344
2345/************************************************************************/
2346/*                                                                      */
2347/*    FUNCTION DESCRIPTION                  zfApSendFailure             */
2348/*      Send failure.                                                   */
2349/*                                                                      */
2350/*    INPUTS                                                            */
2351/*      dev : device pointer                                            */
2352/*      addr : receiver address                                         */
2353/*                                                                      */
2354/*    OUTPUTS                                                           */
2355/*      None                                                            */
2356/*                                                                      */
2357/*    AUTHOR                                                            */
2358/*      Stephen Chen        Atheros Communications, INC.    2007.1      */
2359/*                                                                      */
2360/************************************************************************/
2361void zfApSendFailure(zdev_t* dev, u8_t* addr)
2362{
2363    u16_t id;
2364    u16_t staAddr[3];
2365    zmw_get_wlan_dev(dev);
2366    zmw_declare_for_critical_section();
2367
2368    staAddr[0] = addr[0] + (((u16_t)addr[1])<<8);
2369    staAddr[1] = addr[2] + (((u16_t)addr[3])<<8);
2370    staAddr[2] = addr[4] + (((u16_t)addr[5])<<8);
2371    zmw_enter_critical_section(dev);
2372    id = zfApFindSta(dev, staAddr);
2373    if (id != 0xffff)
2374    {
2375        /* Send failture : Add 3 minutes to inactive time that will */
2376        /*                 will make STA been kicked out soon */
2377        wd->ap.staTable[id].time -= (3*ZM_TICK_PER_MINUTE);
2378    }
2379    zmw_leave_critical_section(dev);
2380}
2381
2382
2383void zfApProcessAction(zdev_t* dev, zbuf_t* buf)
2384{
2385    u8_t category;
2386
2387    //zmw_get_wlan_dev(dev);
2388
2389    //zmw_declare_for_critical_section();
2390
2391    category = zmw_rx_buf_readb(dev, buf, 24);
2392
2393    switch (category)
2394    {
2395    case ZM_WLAN_BLOCK_ACK_ACTION_FRAME:
2396        zfAggBlockAckActionFrame(dev, buf);
2397        break;
2398    default:
2399        break;
2400    }
2401
2402    return;
2403}
2404