Merge branch 'for-linus' of git://www.jni.nu/cris
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / otus / 80211core / cmmap.c
CommitLineData
4bd43f50
LR
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
92363b52
JP
144 id = zfApFindSta(dev, addr);
145 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
167 id = zfApFindSta(dev, addr);
168 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
194 id = zfApFindSta(dev, addr);
195 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
240 id = zfApFindSta(dev, addr);
241 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
267 id = zfApFindSta(dev, addr);
268 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
297 id = zfApFindSta(dev, addr);
298 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
330 id = zfApFindSta(dev, addr);
331 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
358 id = zfApFindSta(dev, addr);
359 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
390 id = zfApFindSta(dev, addr);
391 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
551 id = zfApFindSta(dev, addr);
552 if (id != 0xffff)
4bd43f50
LR
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
92363b52
JP
616 id = zfApFindSta(dev, addr);
617 if (id != 0xffff)
4bd43f50
LR
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 {
92363b52
JP
662 psBuf = zfQueueGetWithMac(dev, wd->ap.uapsdQ, (u8_t*)addr, &mb);
663 if (psBuf != NULL)
4bd43f50
LR
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
92363b52
JP
745 index = zfApFindSta(dev, addr);
746 if (index != 0xffff)
4bd43f50
LR
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) */
92363b52
JP
979 offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP);
980 if (offset == 0xffff)
4bd43f50
LR
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 */
92363b52
JP
1063 ret = zfApAddSta(dev, src, ZM_STATE_AUTH, apId, 0, 0, 0);
1064 if (ret != 0xffff)
4bd43f50
LR
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 */
92363b52
JP
1195 offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID);
1196 if (offset != 0xffff)
4bd43f50
LR
1197 {
1198 k = 0;
1199 for (j = 0; j < wd->ap.vapNumber; j++)
1200 {
92363b52
JP
1201 tmp = zmw_buf_readb(dev, buf, offset+1);
1202 if (tmp
4bd43f50
LR
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 {
92363b52
JP
1218 tmp = zmw_buf_readb(dev, buf, offset+2+i);
1219 if (tmp
4bd43f50
LR
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 */
92363b52
JP
1243 offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE);
1244 if (offset != 0xffff)
4bd43f50
LR
1245 {
1246 /* 11g STA */
1247 staType = 1;
1248 }
1249 //CWYang(+)
92363b52
JP
1250 offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY);
1251 if (offset != 0xffff)
4bd43f50
LR
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 */
92363b52
JP
1274 offset = zfFindWifiElement(dev, buf, 2, 0);
1275 if (offset != 0xffff)
4bd43f50
LR
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 {
92363b52
JP
1289 offset = zfFindElement(dev, buf, ZM_WLAN_EID_WPA_IE);
1290 if (offset != 0xffff)
4bd43f50
LR
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 */
92363b52
JP
1431 offset = zfFindElement(dev, buf, ZM_WLAN_EID_SUPPORT_RATE);
1432 if (offset == 0xffff)
4bd43f50
LR
1433 return;
1434 length = zmw_rx_buf_readb(dev, buf, offset + 1);
1435
1436 /* extended supported rates */
92363b52
JP
1437 offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE);
1438 if (offset == 0xffff)
4bd43f50
LR
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 */
92363b52
JP
1453 offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY);
1454 if (offset != 0xffff) {
4bd43f50
LR
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 */
92363b52
JP
1507 aid = zfApFindSta(dev, src);
1508 if (aid != 0xffff)
4bd43f50
LR
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 */
92363b52
JP
1529 aid = zfApFindSta(dev, src);
1530 if (aid != 0xffff)
4bd43f50
LR
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#if 0
1548 zmw_get_wlan_dev(dev);
1549
1550 zm_msg0_mm(ZM_LV_0, "Rx probersp");
1551
1552 /* Gather scan result */
1553
1554 //zm_debug_msg1("bssList Count = ", wd->sta.bssList.bssCount);
1555 /* return if not in scanning */
1556 if ((wd->heartBeatNotification & ZM_BSSID_LIST_SCAN)
1557 != ZM_BSSID_LIST_SCAN)
1558 {
1559 return;
1560 }
1561
1562 //if ( wd->sta.pUpdateBssList->bssCount == ZM_MAX_BSS )
1563 if ( wd->sta.bssList.bssCount == ZM_MAX_BSS )
1564 {
1565 return;
1566 }
1567
1568 zfProcessProbeRsp(dev, buf, AddInfo);
1569
1570#endif
1571}
1572
1573/************************************************************************/
1574/* */
1575/* FUNCTION DESCRIPTION zfApAddIeSsid */
1576/* Add AP information element SSID to buffer. */
1577/* */
1578/* INPUTS */
1579/* dev : device pointer */
1580/* buf : buffer to add information element */
1581/* offset : add information element from this offset */
1582/* vap : virtual AP ID */
1583/* */
1584/* OUTPUTS */
1585/* buffer offset after adding information element */
1586/* */
1587/* AUTHOR */
1588/* Stephen Chen ZyDAS Technology Corporation 2005.11 */
1589/* */
1590/************************************************************************/
1591u16_t zfApAddIeSsid(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
1592{
1593 u16_t i;
1594
1595 zmw_get_wlan_dev(dev);
1596
1597 /* Element ID */
1598 zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
1599
1600 /* Element Length */
1601 zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.ssidLen[vap]);
1602
1603 /* Information : SSID */
1604 for (i=0; i<wd->ap.ssidLen[vap]; i++)
1605 {
1606 zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.ssid[vap][i]);
1607 }
1608
1609 return offset;
1610}
1611
1612
1613/************************************************************************/
1614/* */
1615/* FUNCTION DESCRIPTION zfApAddIeTim */
1616/* Add AP information element TIM to buffer. */
1617/* */
1618/* INPUTS */
1619/* dev : device pointer */
1620/* buf : buffer to add information element */
1621/* offset : add information element from this offset */
1622/* vap : virtual AP ID */
1623/* */
1624/* OUTPUTS */
1625/* buffer offset after adding information element */
1626/* */
1627/* AUTHOR */
1628/* Stephen Chen ZyDAS Technology Corporation 2005.11 */
1629/* */
1630/************************************************************************/
1631u16_t zfApAddIeTim(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
1632{
1633 u8_t uniBitMap[9];
1634 u16_t highestByte;
1635 u16_t i;
1636 u16_t lenOffset;
1637 u16_t id;
1638 u16_t dst[3];
1639 u16_t aid;
1640 u16_t bitPosition;
1641 u16_t bytePosition;
1642 zbuf_t* psBuf;
1643 zbuf_t* tmpBufArray[ZM_UNI_ARRAY_SIZE];
1644 u16_t tmpBufArraySize = 0;
1645
1646 zmw_get_wlan_dev(dev);
1647
1648 zmw_declare_for_critical_section();
1649
1650 /* Element ID */
1651 zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_TIM);
1652
1653 /* offset of Element Length */
1654 lenOffset = offset++;
1655
1656 /* Information : TIM */
1657 /* DTIM count */
1658 /* TODO : Doesn't work for Virtual AP's case */
1659 wd->CurrentDtimCount++;
1660 if (wd->CurrentDtimCount >= wd->dtim)
1661 {
1662 wd->CurrentDtimCount = 0;
1663 }
1664 zmw_tx_buf_writeb(dev, buf, offset++, wd->CurrentDtimCount);
1665 /* DTIM period */
1666 zmw_tx_buf_writeb(dev, buf, offset++, wd->dtim);
1667 /* bitmap offset */
1668 zmw_tx_buf_writeb(dev, buf, offset++, 0);
1669
1670 /* Update BCMC bit */
1671 if (wd->CurrentDtimCount == 0)
1672 {
1673 zmw_enter_critical_section(dev);
1674 wd->ap.timBcmcBit[vap] = (wd->ap.bcmcTail[vap]!=wd->ap.bcmcHead[vap])?1:0;
1675 zmw_leave_critical_section(dev);
1676 }
1677 else
1678 {
1679 wd->ap.timBcmcBit[vap] = 0;
1680 }
1681
1682 /* Update Unicast bitmap */
1683 /* reset bit map */
1684 for (i=0; i<9; i++)
1685 {
1686 uniBitMap[i] = 0;
1687 }
1688 highestByte = 0;
1689#if 1
1690
1691 zmw_enter_critical_section(dev);
1692
1693 id = wd->ap.uniHead;
1694 while (id != wd->ap.uniTail)
1695 {
1696 psBuf = wd->ap.uniArray[id];
1697
1698 /* TODO : Aging PS frame after queuing for more than 10 seconds */
1699
1700 /* get destination STA's aid */
1701 dst[0] = zmw_tx_buf_readh(dev, psBuf, 0);
1702 dst[1] = zmw_tx_buf_readh(dev, psBuf, 2);
1703 dst[2] = zmw_tx_buf_readh(dev, psBuf, 4);
92363b52
JP
1704 aid = zfApFindSta(dev, dst);
1705 if (aid != 0xffff)
4bd43f50
LR
1706 {
1707 if (wd->ap.staTable[aid].psMode != 0)
1708 {
1709 zm_msg1_mm(ZM_LV_0, "aid=",aid);
1710 aid++;
1711 zm_assert(aid<=64);
1712 bitPosition = (1 << (aid & 0x7));
1713 bytePosition = (aid >> 3);
1714 uniBitMap[bytePosition] |= bitPosition;
1715
1716 if (bytePosition>highestByte)
1717 {
1718 highestByte = bytePosition;
1719 }
1720 id = (id+1) & (ZM_UNI_ARRAY_SIZE-1);
1721 }
1722 else
1723 {
1724 zm_msg0_mm(ZM_LV_0, "Send PS frame which STA no longer in PS mode");
1725 /* Send PS frame which STA no longer in PS mode */
1726 zfApRemoveFromPsQueue(dev, id, dst);
1727 tmpBufArray[tmpBufArraySize++] = psBuf;
1728 }
1729 }
1730 else
1731 {
1732 zm_msg0_mm(ZM_LV_0, "Free garbage PS frame");
1733 /* Free garbage PS frame */
1734 zfApRemoveFromPsQueue(dev, id, dst);
1735 zfwBufFree(dev, psBuf, 0);
1736 }
1737 }
1738
1739 zmw_leave_critical_section(dev);
1740#endif
1741
1742 zfQueueGenerateUapsdTim(dev, wd->ap.uapsdQ, uniBitMap, &highestByte);
1743
1744 zm_msg1_mm(ZM_LV_3, "bm=",uniBitMap[0]);
1745 zm_msg1_mm(ZM_LV_3, "highestByte=",highestByte);
1746 zm_msg1_mm(ZM_LV_3, "timBcmcBit[]=",wd->ap.timBcmcBit[vap]);
1747
1748 /* bitmap */
1749 zmw_tx_buf_writeb(dev, buf, offset++,
1750 uniBitMap[0] | wd->ap.timBcmcBit[vap]);
1751 for (i=0; i<highestByte; i++)
1752 {
1753 zmw_tx_buf_writeb(dev, buf, offset++, uniBitMap[i+1]);
1754 }
1755
1756 /* Element Length */
1757 zmw_tx_buf_writeb(dev, buf, lenOffset, highestByte+4);
1758
1759 for (i=0; i<tmpBufArraySize; i++)
1760 {
1761 /* Put to VTXQ[ac] */
1762 zfPutVtxq(dev, tmpBufArray[i]);
1763 }
1764 /* Push VTXQ[ac] */
1765 zfPushVtxq(dev);
1766
1767 return offset;
1768}
1769
1770
1771
1772/************************************************************************/
1773/* */
1774/* FUNCTION DESCRIPTION zfApRemoveFromPsQueue */
1775/* Remove zbuf from PS queue. */
1776/* */
1777/* INPUTS */
1778/* dev : device pointer */
1779/* id : index in ps queue */
1780/* */
1781/* OUTPUTS */
1782/* more data bit */
1783/* */
1784/* AUTHOR */
1785/* Stephen Chen Atheros Communications, INC. 2007.1 */
1786/* */
1787/************************************************************************/
1788u8_t zfApRemoveFromPsQueue(zdev_t* dev, u16_t id, u16_t* addr)
1789{
1790 u16_t dst[3];
1791 u16_t nid;
1792 u8_t moreData = 0;
1793 zmw_get_wlan_dev(dev);
1794
1795 wd->ap.uniTail = (wd->ap.uniTail-1) & (ZM_UNI_ARRAY_SIZE-1);
1796 while (id != wd->ap.uniTail)
1797 {
1798 nid = (id + 1) & (ZM_UNI_ARRAY_SIZE - 1);
1799 wd->ap.uniArray[id] = wd->ap.uniArray[nid];
1800
1801 /* Search until tail to config more data bit */
1802 dst[0] = zmw_buf_readh(dev, wd->ap.uniArray[id], 0);
1803 dst[1] = zmw_buf_readh(dev, wd->ap.uniArray[id], 2);
1804 dst[2] = zmw_buf_readh(dev, wd->ap.uniArray[id], 4);
1805 if ((addr[0] == dst[0]) && (addr[1] == dst[1])
1806 && (addr[2] == dst[2]))
1807 {
1808 moreData = 0x20;
1809 }
1810
1811 id = nid;
1812 }
1813 return moreData;
1814}
1815
1816/************************************************************************/
1817/* */
1818/* FUNCTION DESCRIPTION zfApAddIeWmePara */
1819/* Add WME Parameter Element to buffer. */
1820/* */
1821/* INPUTS */
1822/* dev : device pointer */
1823/* buf : buffer to add information element */
1824/* offset : add information element from this offset */
1825/* vap : virtual AP ID */
1826/* */
1827/* OUTPUTS */
1828/* buffer offset after adding information element */
1829/* */
1830/* AUTHOR */
1831/* Stephen Chen ZyDAS Technology Corporation 2006.1 */
1832/* */
1833/************************************************************************/
1834u16_t zfApAddIeWmePara(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
1835{
1836 zmw_get_wlan_dev(dev);
1837
1838 /* Element ID */
1839 zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WIFI_IE);
1840
1841 /* Element Length */
1842 zmw_tx_buf_writeb(dev, buf, offset++, 24);
1843
1844 /* OUI */
1845 zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1846 zmw_tx_buf_writeb(dev, buf, offset++, 0x50);
1847 zmw_tx_buf_writeb(dev, buf, offset++, 0xF2);
1848 zmw_tx_buf_writeb(dev, buf, offset++, 0x02);
1849 zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
1850 zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
1851
1852 /* QoS Info */
1853 if (wd->ap.uapsdEnabled)
1854 {
1855 zmw_tx_buf_writeb(dev, buf, offset++, 0x81);
1856 }
1857 else
1858 {
1859 zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
1860 }
1861
1862 /* Reserved */
1863 zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1864
1865 /* Best Effort AC parameters */
1866 zmw_tx_buf_writeb(dev, buf, offset++, 0x03);
1867 zmw_tx_buf_writeb(dev, buf, offset++, 0xA4);
1868 zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1869 zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1870 /* Backfround AC parameters */
1871 zmw_tx_buf_writeb(dev, buf, offset++, 0x27);
1872 zmw_tx_buf_writeb(dev, buf, offset++, 0xA4);
1873 zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1874 zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1875 /* Video AC parameters */
1876 zmw_tx_buf_writeb(dev, buf, offset++, 0x42);
1877 zmw_tx_buf_writeb(dev, buf, offset++, 0x43);
1878 zmw_tx_buf_writeb(dev, buf, offset++, 0x5E);
1879 zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1880 /* Voice AC parameters */
1881 zmw_tx_buf_writeb(dev, buf, offset++, 0x62);
1882 zmw_tx_buf_writeb(dev, buf, offset++, 0x32);
1883 zmw_tx_buf_writeb(dev, buf, offset++, 0x2F);
1884 zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
1885
1886 return offset;
1887}
1888
1889
1890/************************************************************************/
1891/* */
1892/* FUNCTION DESCRIPTION zfApSendBeacon */
1893/* Sned AP mode beacon. */
1894/* */
1895/* INPUTS */
1896/* dev : device pointer */
1897/* */
1898/* OUTPUTS */
1899/* none */
1900/* */
1901/* AUTHOR */
1902/* Stephen Chen ZyDAS Technology Corporation 2005.11 */
1903/* */
1904/************************************************************************/
1905void zfApSendBeacon(zdev_t* dev)
1906{
1907 zbuf_t* buf;
1908 u16_t offset;
1909 u16_t vap;
1910 u16_t seq;
1911
1912 zmw_get_wlan_dev(dev);
1913
1914 zmw_declare_for_critical_section();
1915
1916 wd->ap.beaconCounter++;
1917 if (wd->ap.beaconCounter >= wd->ap.vapNumber)
1918 {
1919 wd->ap.beaconCounter = 0;
1920 }
1921 vap = wd->ap.beaconCounter;
1922
1923
1924 zm_msg1_mm(ZM_LV_2, "Send beacon, vap=", vap);
1925
1926 /* TBD : Maximum size of beacon */
92363b52
JP
1927 buf = zfwBufAllocate(dev, 1024);
1928 if (buf == NULL)
4bd43f50
LR
1929 {
1930 zm_msg0_mm(ZM_LV_0, "Alloc beacon buf Fail!");
1931 return;
1932 }
1933
1934 offset = 0;
1935
1936 /* wlan header */
1937 /* Frame control */
1938 zmw_tx_buf_writeh(dev, buf, offset, 0x0080);
1939 offset+=2;
1940 /* Duration */
1941 zmw_tx_buf_writeh(dev, buf, offset, 0x0000);
1942 offset+=2;
1943 /* Address 1 */
1944 zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
1945 offset+=2;
1946 zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
1947 offset+=2;
1948 zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
1949 offset+=2;
1950 /* Address 2 */
1951 zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
1952 offset+=2;
1953 zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
1954 offset+=2;
1955#ifdef ZM_VAPMODE_MULTILE_SSID
1956 zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]); //Multiple SSID
1957#else
1958 zmw_tx_buf_writeh(dev, buf, offset, (wd->macAddr[2]+(vap<<8))); //VAP
1959#endif
1960 offset+=2;
1961 /* Address 3 */
1962 zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
1963 offset+=2;
1964 zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
1965 offset+=2;
1966#ifdef ZM_VAPMODE_MULTILE_SSID
1967 zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]); //Multiple SSID
1968#else
1969 zmw_tx_buf_writeh(dev, buf, offset, (wd->macAddr[2]+(vap<<8))); //VAP
1970#endif
1971 offset+=2;
1972
1973 /* Sequence number */
1974 zmw_enter_critical_section(dev);
1975 seq = ((wd->mmseq++)<<4);
1976 zmw_leave_critical_section(dev);
1977 zmw_tx_buf_writeh(dev, buf, offset, seq);
1978 offset+=2;
1979
1980 /* 24-31 Time Stamp : hardware will fill this field */
1981 zmw_tx_buf_writeh(dev, buf, offset, 0);
1982 zmw_tx_buf_writeh(dev, buf, offset+2, 0);
1983 zmw_tx_buf_writeh(dev, buf, offset+4, 0);
1984 zmw_tx_buf_writeh(dev, buf, offset+6, 0);
1985 offset+=8;
1986
1987 /* Beacon Interval */
1988 zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval);
1989 offset+=2;
1990
1991 /* Capability */
1992 zmw_tx_buf_writeh(dev, buf, offset, wd->ap.capab[vap]);
1993 offset+=2;
1994
1995 /* SSID */
1996 if (wd->ap.hideSsid[vap] == 0)
1997 {
1998 offset = zfApAddIeSsid(dev, buf, offset, vap);
1999 }
2000 else
2001 {
2002 zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
2003 zmw_tx_buf_writeb(dev, buf, offset++, 0);
2004
2005 }
2006
2007 /* Support Rate */
2008 if ( wd->frequency < 3000 )
2009 {
2010 offset = zfMmAddIeSupportRate(dev, buf, offset,
2011 ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
2012 }
2013 else
2014 {
2015 offset = zfMmAddIeSupportRate(dev, buf, offset,
2016 ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
2017 }
2018
2019 /* DS parameter set */
2020 offset = zfMmAddIeDs(dev, buf, offset);
2021
2022 /* TIM */
2023 offset = zfApAddIeTim(dev, buf, offset, vap);
2024
2025 /* If WLAN Type is not PURE B */
2026 if (wd->ap.wlanType[vap] != ZM_WLAN_TYPE_PURE_B)
2027 {
2028 if ( wd->frequency < 3000 )
2029 {
2030 /* ERP Information */
2031 offset = zfMmAddIeErp(dev, buf, offset);
2032
2033 /* Extended Supported Rates */
2034 offset = zfMmAddIeSupportRate(dev, buf, offset,
2035 ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
2036 }
2037 }
2038
2039 /* TODO : country information */
2040 /* TODO : RSN */
2041 if (wd->ap.wpaSupport[vap] == 1)
2042 {
2043 offset = zfMmAddIeWpa(dev, buf, offset, vap);
2044 }
2045
2046 /* WME Parameters */
2047 if (wd->ap.qosMode == 1)
2048 {
2049 offset = zfApAddIeWmePara(dev, buf, offset, vap);
2050 }
2051
2052 /* HT Capabilities Info */
2053 offset = zfMmAddHTCapability(dev, buf, offset);
2054
2055 /* Extended HT Capabilities Info */
2056 offset = zfMmAddExtendedHTCapability(dev, buf, offset);
2057
2058 /* 1212 : write to beacon fifo */
2059 /* 1221 : write to share memory */
2060 zfHpSendBeacon(dev, buf, offset);
2061
2062 /* Free beacon buffer */
2063 /* TODO: In order to fit the madwifi beacon architecture, we need to
2064 free beacon buffer in the HAL layer.
2065 */
2066
2067 //zfwBufFree(dev, buf, 0);
2068}
2069
2070
2071/************************************************************************/
2072/* */
2073/* FUNCTION DESCRIPTION zfIntrabssForward */
2074/* Called to transmit intra-BSS frame from upper layer. */
2075/* */
2076/* INPUTS */
2077/* dev : device pointer */
2078/* buf : buffer pointer */
2079/* vap : virtual AP */
2080/* */
2081/* OUTPUTS */
2082/* 1 : unicast intras-BSS frame */
2083/* 0 : other frames */
2084/* */
2085/* AUTHOR */
2086/* Stephen ZyDAS Technology Corporation 2005.11 */
2087/* */
2088/************************************************************************/
2089u16_t zfIntrabssForward(zdev_t* dev, zbuf_t* buf, u8_t srcVap)
2090{
2091 u16_t err;
2092 u16_t asocFlag = 0;
2093 u16_t dst[3];
2094 u16_t aid;
2095 u16_t staState;
2096 zbuf_t* txBuf;
2097 u16_t len;
2098 u16_t i;
2099 u16_t temp;
2100 u16_t ret;
2101 u8_t vap = 0;
2102#ifdef ZM_ENABLE_NATIVE_WIFI
2103 dst[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
2104 dst[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
2105 dst[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
2106#else
2107 dst[0] = zmw_rx_buf_readh(dev, buf, 0);
2108 dst[1] = zmw_rx_buf_readh(dev, buf, 2);
2109 dst[2] = zmw_rx_buf_readh(dev, buf, 4);
2110#endif // ZM_ENABLE_NATIVE_WIFI
2111
2112 /* Do Intra-BSS forward(data copy) if necessary*/
2113 if ((dst[0]&0x1) != 0x1)
2114 {
2115 aid = zfApGetSTAInfo(dev, dst, &staState, &vap);
2116 if ((aid != 0xffff) && (staState == ZM_STATE_ASOC) && (srcVap == vap))
2117 {
2118 asocFlag = 1;
2119 zm_msg0_rx(ZM_LV_2, "Intra-BSS forward : asoc STA");
2120 }
2121
2122 }
2123 else
2124 {
2125 vap = srcVap;
2126 zm_msg0_rx(ZM_LV_2, "Intra-BSS forward : BCorMC");
2127 }
2128
2129 /* destination address = associated STA or BC/MC */
2130 if ((asocFlag == 1) || ((dst[0]&0x1) == 0x1))
2131 {
2132 /* Allocate frame */
92363b52
JP
2133 txBuf = zfwBufAllocate(dev, ZM_RX_FRAME_SIZE);
2134 if (txBuf == NULL)
4bd43f50
LR
2135 {
2136 zm_msg0_rx(ZM_LV_1, "Alloc intra-bss buf Fail!");
2137 goto zlAllocError;
2138 }
2139
2140 /* Copy frame */
2141 len = zfwBufGetSize(dev, buf);
2142 for (i=0; i<len; i+=2)
2143 {
2144 temp = zmw_rx_buf_readh(dev, buf, i);
2145 zmw_tx_buf_writeh(dev, txBuf, i, temp);
2146 }
2147 zfwBufSetSize(dev, txBuf, len);
2148
2149#ifdef ZM_ENABLE_NATIVE_WIFI
2150 /* Tx-A2 = Rx-A1, Tx-A3 = Rx-A2, Tx-A1 = Rx-A3 */
2151 for (i=0; i<6; i+=2)
2152 {
2153 temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+i);
2154 zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A2_OFFSET+i, temp);
2155 temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+i);
2156 zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A3_OFFSET+i, temp);
2157 temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+i);
2158 zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A1_OFFSET+i, temp);
2159 }
2160
2161 #endif
2162
2163 /* Transmit frame */
2164 /* Return error if port is disabled */
92363b52
JP
2165 err = zfTxPortControl(dev, txBuf, vap);
2166 if (err == ZM_PORT_DISABLED)
4bd43f50
LR
2167 {
2168 err = ZM_ERR_TX_PORT_DISABLED;
2169 goto zlTxError;
2170 }
2171
2172#if 1
2173 /* AP : Buffer frame for power saving STA */
92363b52
JP
2174 ret = zfApBufferPsFrame(dev, txBuf, vap);
2175 if (ret == 0)
4bd43f50
LR
2176 {
2177 /* forward frame if not been buffered */
2178 #if 1
2179 /* Put to VTXQ[ac] */
2180 ret = zfPutVtxq(dev, txBuf);
2181 /* Push VTXQ[ac] */
2182 zfPushVtxq(dev);
2183 #else
2184 zfTxSendEth(dev, txBuf, vap, ZM_INTERNAL_ALLOC_BUF, 0);
2185 #endif
2186
2187 }
2188#endif
2189 }
2190 return asocFlag;
2191
2192zlTxError:
2193 zfwBufFree(dev, txBuf, 0);
2194zlAllocError:
2195 return asocFlag;
2196}
2197
2198struct zsMicVar* zfApGetRxMicKey(zdev_t* dev, zbuf_t* buf)
2199{
2200 u8_t sa[6];
2201 u16_t id = 0, macAddr[3];
2202
2203 zmw_get_wlan_dev(dev);
2204
2205 zfCopyFromRxBuffer(dev, buf, sa, ZM_WLAN_HEADER_A2_OFFSET, 6);
2206
2207 macAddr[0] = sa[0] + (sa[1] << 8);
2208 macAddr[1] = sa[2] + (sa[3] << 8);
2209 macAddr[2] = sa[4] + (sa[5] << 8);
2210
92363b52
JP
2211 id = zfApFindSta(dev, macAddr);
2212 if (id != 0xffff)
4bd43f50
LR
2213 return (&wd->ap.staTable[id].rxMicKey);
2214
2215 return NULL;
2216}
2217
2218struct zsMicVar* zfApGetTxMicKey(zdev_t* dev, zbuf_t* buf, u8_t* qosType)
2219{
2220 u8_t da[6];
2221 u16_t id = 0, macAddr[3];
2222
2223 zmw_get_wlan_dev(dev);
2224
2225 zfCopyFromIntTxBuffer(dev, buf, da, 0, 6);
2226
2227 macAddr[0] = da[0] + (da[1] << 8);
2228 macAddr[1] = da[2] + (da[3] << 8);
2229 macAddr[2] = da[4] + (da[5] << 8);
2230
2231 if ((macAddr[0] & 0x1))
2232 {
2233 return (&wd->ap.bcMicKey[0]);
2234 }
2235 else if ((id = zfApFindSta(dev, macAddr)) != 0xffff)
2236 {
2237 *qosType = wd->ap.staTable[id].qosType;
2238 return (&wd->ap.staTable[id].txMicKey);
2239 }
2240
2241 return NULL;
2242}
2243
2244u16_t zfApUpdatePsBit(zdev_t* dev, zbuf_t* buf, u8_t* vap, u8_t* uapsdTrig)
2245{
2246 u16_t staState;
2247 u16_t aid;
2248 u16_t psBit;
2249 u16_t src[3];
2250 u16_t dst[1];
2251 u16_t i;
2252
2253 zmw_get_wlan_dev(dev);
2254
2255 src[0] = zmw_rx_buf_readh(dev, buf, 10);
2256 src[1] = zmw_rx_buf_readh(dev, buf, 12);
2257 src[2] = zmw_rx_buf_readh(dev, buf, 14);
2258
2259 if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3)
2260 {
2261 /* AP */
2262 dst[0] = zmw_rx_buf_readh(dev, buf, 4);
2263
2264 psBit = (zmw_rx_buf_readb(dev, buf, 1) & 0x10) >> 4;
2265 /* Get AID and update STA PS mode */
2266 aid = zfApGetSTAInfoAndUpdatePs(dev, src, &staState, vap, psBit, uapsdTrig);
2267
2268 /* if STA not associated, send deauth */
2269 if ((aid == 0xffff) || (staState != ZM_STATE_ASOC))
2270 {
2271 if ((dst[0]&0x1)==0)
2272 {
2273 zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 0x7,
2274 0, 0);
2275 }
2276
2277 return ZM_ERR_STA_NOT_ASSOCIATED;
2278 }
2279 } /* if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3) */
2280 else
2281 {
2282 /* WDS */
2283 for (i=0; i<ZM_MAX_WDS_SUPPORT; i++)
2284 {
2285 if ((wd->ap.wds.wdsBitmap & (1<<i)) != 0)
2286 {
2287 if ((src[0] == wd->ap.wds.macAddr[i][0])
2288 && (src[1] == wd->ap.wds.macAddr[i][1])
2289 && (src[2] == wd->ap.wds.macAddr[i][2]))
2290 {
2291 *vap = 0x20 + i;
2292 break;
2293 }
2294 }
2295 }
2296 }
2297 return ZM_SUCCESS;
2298}
2299
2300void zfApProcessPsPoll(zdev_t* dev, zbuf_t* buf)
2301{
2302 u16_t src[3];
2303 u16_t dst[3];
2304 zbuf_t* psBuf = NULL;
2305 u16_t id;
2306 u8_t moreData = 0;
2307
2308 zmw_get_wlan_dev(dev);
2309
2310 zmw_declare_for_critical_section();
2311
2312 src[0] = zmw_tx_buf_readh(dev, buf, 10);
2313 src[1] = zmw_tx_buf_readh(dev, buf, 12);
2314 src[2] = zmw_tx_buf_readh(dev, buf, 14);
2315
2316 /* Find ps buffer for PsPoll */
2317 zmw_enter_critical_section(dev);
2318 id = wd->ap.uniHead;
2319 while (id != wd->ap.uniTail)
2320 {
2321 psBuf = wd->ap.uniArray[id];
2322
2323 dst[0] = zmw_tx_buf_readh(dev, psBuf, 0);
2324 dst[1] = zmw_tx_buf_readh(dev, psBuf, 2);
2325 dst[2] = zmw_tx_buf_readh(dev, psBuf, 4);
2326
2327 if ((src[0] == dst[0]) && (src[1] == dst[1]) && (src[2] == dst[2]))
2328 {
2329 moreData = zfApRemoveFromPsQueue(dev, id, src);
2330 break;
2331 }
2332 else
2333 {
2334 psBuf = NULL;
2335 }
2336 id = (id + 1) & (ZM_UNI_ARRAY_SIZE - 1);
2337 }
2338 zmw_leave_critical_section(dev);
2339
2340 /* Send ps buffer */
2341 if (psBuf != NULL)
2342 {
2343 /* Send with more data bit */
2344 zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, moreData);
2345 }
2346
2347 return;
2348}
2349
2350void zfApSetProtectionMode(zdev_t* dev, u16_t mode)
2351{
2352 zmw_get_wlan_dev(dev);
2353
2354 if (mode == 0)
2355 {
2356 if (wd->ap.protectionMode != mode)
2357 {
2358 /* Write MAC&PHY registers to disable protection */
2359
2360 wd->ap.protectionMode = mode;
2361 }
2362
2363 }
2364 else
2365 {
2366 if (wd->ap.protectionMode != mode)
2367 {
2368 /* Write MAC&PHY registers to enable protection */
2369
2370 wd->ap.protectionMode = mode;
2371 }
2372 }
2373 return;
2374}
2375
2376
2377/************************************************************************/
2378/* */
2379/* FUNCTION DESCRIPTION zfApSendFailure */
2380/* Send failure. */
2381/* */
2382/* INPUTS */
2383/* dev : device pointer */
2384/* addr : receiver address */
2385/* */
2386/* OUTPUTS */
2387/* None */
2388/* */
2389/* AUTHOR */
2390/* Stephen Chen Atheros Communications, INC. 2007.1 */
2391/* */
2392/************************************************************************/
2393void zfApSendFailure(zdev_t* dev, u8_t* addr)
2394{
2395 u16_t id;
2396 u16_t staAddr[3];
2397 zmw_get_wlan_dev(dev);
2398 zmw_declare_for_critical_section();
2399
2400 staAddr[0] = addr[0] + (((u16_t)addr[1])<<8);
2401 staAddr[1] = addr[2] + (((u16_t)addr[3])<<8);
2402 staAddr[2] = addr[4] + (((u16_t)addr[5])<<8);
2403 zmw_enter_critical_section(dev);
92363b52
JP
2404 id = zfApFindSta(dev, staAddr);
2405 if (id != 0xffff)
4bd43f50
LR
2406 {
2407 /* Send failture : Add 3 minutes to inactive time that will */
2408 /* will make STA been kicked out soon */
2409 wd->ap.staTable[id].time -= (3*ZM_TICK_PER_MINUTE);
2410 }
2411 zmw_leave_critical_section(dev);
2412}
2413
2414
2415void zfApProcessAction(zdev_t* dev, zbuf_t* buf)
2416{
2417 u8_t category;
2418
2419 //zmw_get_wlan_dev(dev);
2420
2421 //zmw_declare_for_critical_section();
2422
2423 category = zmw_rx_buf_readb(dev, buf, 24);
2424
2425 switch (category)
2426 {
2427 case ZM_WLAN_BLOCK_ACK_ACTION_FRAME:
2428 zfAggBlockAckActionFrame(dev, buf);
2429 break;
2430 default:
2431 break;
2432 }
2433
2434 return;
2435}