import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / connectivity / conn_soc / drv_wlan / mt_wifi / wlan / mgmt / tdls.c
1 /*
2 ** $Id: tdls.c#1 $
3 */
4
5 /*! \file tdls.c
6 \brief This file includes IEEE802.11z TDLS support.
7 */
8
9
10 /*
11 ** $Log: tdls.c $
12 *
13 * 11 13 2013 vend_samp.lin
14 * NULL
15 * Initial version.
16 */
17
18 /*******************************************************************************
19 * C O M P I L E R F L A G S
20 ********************************************************************************
21 */
22
23 /*******************************************************************************
24 * E X T E R N A L R E F E R E N C E S
25 ********************************************************************************
26 */
27 #include "precomp.h"
28
29 #if (CFG_SUPPORT_TDLS == 1)
30 #include "gl_wext.h"
31 #include "tdls.h"
32 #include "gl_cfg80211.h"
33 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
34 #include <uapi/linux/nl80211.h>
35 #endif
36 /*******************************************************************************
37 * C O N S T A N T S
38 ********************************************************************************
39 */
40
41 /*******************************************************************************
42 * F U N C T I O N D E C L A R A T I O N S
43 ********************************************************************************
44 */
45 static VOID
46 TdlsCmdTestRxIndicatePkts (
47 GLUE_INFO_T *prGlueInfo,
48 struct sk_buff *prSkb
49 );
50
51 #if TDLS_CFG_CMD_TEST
52 static void
53 TdlsCmdTestAddPeer(
54 P_GLUE_INFO_T prGlueInfo,
55 UINT_8 *prInBuf,
56 UINT_32 u4InBufLen
57 );
58
59 static void
60 TdlsCmdTestChSwProhibitedBitSet(
61 P_GLUE_INFO_T prGlueInfo,
62 UINT_8 *prInBuf,
63 UINT_32 u4InBufLen
64 );
65
66 static void
67 TdlsCmdTestChSwReqRecv(
68 P_GLUE_INFO_T prGlueInfo,
69 UINT_8 *prInBuf,
70 UINT_32 u4InBufLen
71 );
72
73 static void
74 TdlsCmdTestChSwRspRecv(
75 P_GLUE_INFO_T prGlueInfo,
76 UINT_8 *prInBuf,
77 UINT_32 u4InBufLen
78 );
79
80 static void
81 TdlsCmdTestChSwTimeoutSkip(
82 P_GLUE_INFO_T prGlueInfo,
83 UINT_8 *prInBuf,
84 UINT_32 u4InBufLen
85 );
86
87 static void
88 TdlsCmdTestDataContSend(
89 GLUE_INFO_T *prGlueInfo,
90 UINT_8 *prInBuf,
91 UINT_32 u4InBufLen
92 );
93
94 static void
95 TdlsCmdTestDataRecv(
96 P_GLUE_INFO_T prGlueInfo,
97 UINT_8 *prInBuf,
98 UINT_32 u4InBufLen
99 );
100
101 static void
102 TdlsCmdTestDataSend(
103 P_GLUE_INFO_T prGlueInfo,
104 UINT_8 *prInBuf,
105 UINT_32 u4InBufLen
106 );
107
108 static void
109 TdlsCmdTestDelay(
110 P_GLUE_INFO_T prGlueInfo,
111 UINT_8 *prInBuf,
112 UINT_32 u4InBufLen
113 );
114
115 static void
116 TdlsCmdTestDiscoveryReqRecv(
117 GLUE_INFO_T *prGlueInfo,
118 UINT_8 *prInBuf,
119 UINT_32 u4InBufLen
120 );
121
122 static void
123 TdlsCmdTestKeepAliveSkip(
124 P_GLUE_INFO_T prGlueInfo,
125 UINT_8 *prInBuf,
126 UINT_32 u4InBufLen
127 );
128
129 static void
130 TdlsCmdTestProhibitedBitSet(
131 P_GLUE_INFO_T prGlueInfo,
132 UINT_8 *prInBuf,
133 UINT_32 u4InBufLen
134 );
135
136 static void
137 TdlsCmdTestPtiReqRecv(
138 P_GLUE_INFO_T prGlueInfo,
139 UINT_8 *prInBuf,
140 UINT_32 u4InBufLen
141 );
142
143 static void
144 TdlsCmdTestPtiRspRecv(
145 P_GLUE_INFO_T prGlueInfo,
146 UINT_8 *prInBuf,
147 UINT_32 u4InBufLen
148 );
149
150 static void
151 TdlsCmdTestPtiTxDoneFail(
152 P_GLUE_INFO_T prGlueInfo,
153 UINT_8 *prInBuf,
154 UINT_32 u4InBufLen
155 );
156
157 static void
158 TdlsCmdTestRvFrame(
159 P_GLUE_INFO_T prGlueInfo,
160 UINT_8 *prInBuf,
161 UINT_32 u4InBufLen
162 );
163
164 static void
165 TdlsCmdTestSetupConfirmRecv(
166 GLUE_INFO_T *prGlueInfo,
167 UINT_8 *prInBuf,
168 UINT_32 u4InBufLen
169 );
170
171 static void
172 TdlsCmdTestSetupReqRecv(
173 GLUE_INFO_T *prGlueInfo,
174 UINT_8 *prInBuf,
175 UINT_32 u4InBufLen
176 );
177
178 static void
179 TdlsCmdTestSetupRspRecv(
180 GLUE_INFO_T *prGlueInfo,
181 UINT_8 *prInBuf,
182 UINT_32 u4InBufLen
183 );
184
185 static void
186 TdlsCmdTestScanCtrl(
187 P_GLUE_INFO_T prGlueInfo,
188 UINT_8 *prInBuf,
189 UINT_32 u4InBufLen
190 );
191
192 static void
193 TdlsCmdTestTearDownRecv(
194 GLUE_INFO_T *prGlueInfo,
195 UINT_8 *prInBuf,
196 UINT_32 u4InBufLen
197 );
198
199 static void
200 TdlsCmdTestTxFailSkip(
201 P_GLUE_INFO_T prGlueInfo,
202 UINT_8 *prInBuf,
203 UINT_32 u4InBufLen
204 );
205
206 static void
207 TdlsCmdTestTxTdlsFrame(
208 P_GLUE_INFO_T prGlueInfo,
209 UINT_8 *prInBuf,
210 UINT_32 u4InBufLen
211 );
212
213 static void
214 TdlsCmdTestTxFrame(
215 P_GLUE_INFO_T prGlueInfo,
216 UINT_8 *prInBuf,
217 UINT_32 u4InBufLen
218 );
219
220 static TDLS_STATUS
221 TdlsCmdTestTxFmeSetupReqBufTranslate(
222 UINT_8 *pCmdBuf,
223 UINT_32 u4BufLen,
224 PARAM_CUSTOM_TDLS_CMD_STRUC_T *prCmd
225 );
226
227 static void
228 TdlsCmdTestUpdatePeer(
229 P_GLUE_INFO_T prGlueInfo,
230 UINT_8 *prInBuf,
231 UINT_32 u4InBufLen
232 );
233
234 static void
235 TdlsCmdTestNullRecv(
236 P_GLUE_INFO_T prGlueInfo,
237 UINT_8 *prInBuf,
238 UINT_32 u4InBufLen
239 );
240
241 static VOID
242 TdlsTimerTestDataContSend(
243 ADAPTER_T *prAdapter,
244 UINT_32 u4Param
245 );
246
247 static TDLS_STATUS
248 TdlsTestChStReqRecv(
249 ADAPTER_T *prAdapter,
250 VOID *pvSetBuffer,
251 UINT_32 u4SetBufferLen,
252 UINT_32 *pu4SetInfoLen
253 );
254
255 static TDLS_STATUS
256 TdlsTestChStRspRecv(
257 ADAPTER_T *prAdapter,
258 VOID *pvSetBuffer,
259 UINT_32 u4SetBufferLen,
260 UINT_32 *pu4SetInfoLen
261 );
262
263 static TDLS_STATUS
264 TdlsTestFrameSend(
265 ADAPTER_T *prAdapter,
266 VOID *pvSetBuffer,
267 UINT_32 u4SetBufferLen,
268 UINT_32 *pu4SetInfoLen
269 );
270
271 static TDLS_STATUS
272 TdlsTestNullRecv(
273 ADAPTER_T *prAdapter,
274 VOID *pvSetBuffer,
275 UINT_32 u4SetBufferLen,
276 UINT_32 *pu4SetInfoLen
277 );
278
279 static TDLS_STATUS
280 TdlsTestPtiReqRecv(
281 ADAPTER_T *prAdapter,
282 VOID *pvSetBuffer,
283 UINT_32 u4SetBufferLen,
284 UINT_32 *pu4SetInfoLen
285 );
286
287 static TDLS_STATUS
288 TdlsTestPtiRspRecv(
289 ADAPTER_T *prAdapter,
290 VOID *pvSetBuffer,
291 UINT_32 u4SetBufferLen,
292 UINT_32 *pu4SetInfoLen
293 );
294
295 static TDLS_STATUS
296 TdlsTestTearDownRecv(
297 ADAPTER_T *prAdapter,
298 VOID *pvSetBuffer,
299 UINT_32 u4SetBufferLen,
300 UINT_32 *pu4SetInfoLen
301 );
302
303 static TDLS_STATUS
304 TdlsTestDataRecv(
305 ADAPTER_T *prAdapter,
306 VOID *pvSetBuffer,
307 UINT_32 u4SetBufferLen,
308 UINT_32 *pu4SetInfoLen
309 );
310
311 static TDLS_STATUS
312 TdlsTestPtiTxFail(
313 ADAPTER_T *prAdapter,
314 VOID *pvSetBuffer,
315 UINT_32 u4SetBufferLen,
316 UINT_32 *pu4SetInfoLen
317 );
318
319 static TDLS_STATUS
320 TdlsTestTdlsFrameSend(
321 ADAPTER_T *prAdapter,
322 VOID *pvSetBuffer,
323 UINT_32 u4SetBufferLen,
324 UINT_32 *pu4SetInfoLen
325 );
326
327 static TDLS_STATUS
328 TdlsTestTxFailSkip(
329 ADAPTER_T *prAdapter,
330 VOID *pvSetBuffer,
331 UINT_32 u4SetBufferLen,
332 UINT_32 *pu4SetInfoLen
333 );
334
335 static TDLS_STATUS
336 TdlsTestKeepAliveSkip(
337 ADAPTER_T *prAdapter,
338 VOID *pvSetBuffer,
339 UINT_32 u4SetBufferLen,
340 UINT_32 *pu4SetInfoLen
341 );
342
343 static TDLS_STATUS
344 TdlsTestChSwTimeoutSkip(
345 ADAPTER_T *prAdapter,
346 VOID *pvSetBuffer,
347 UINT_32 u4SetBufferLen,
348 UINT_32 *pu4SetInfoLen
349 );
350
351 static TDLS_STATUS
352 TdlsTestScanSkip(
353 ADAPTER_T *prAdapter,
354 VOID *pvSetBuffer,
355 UINT_32 u4SetBufferLen,
356 UINT_32 *pu4SetInfoLen
357 );
358
359 static TDLS_STATUS
360 TdlsChSwConf(
361 ADAPTER_T *prAdapter,
362 VOID *pvSetBuffer,
363 UINT_32 u4SetBufferLen,
364 UINT_32 *pu4SetInfoLen
365 );
366
367 static void
368 TdlsCmdChSwConf(
369 P_GLUE_INFO_T prGlueInfo,
370 UINT_8 *prInBuf,
371 UINT_32 u4InBufLen
372 );
373
374 static void
375 TdlsCmdInfoDisplay(
376 GLUE_INFO_T *prGlueInfo,
377 UINT_8 *prInBuf,
378 UINT_32 u4InBufLen
379 );
380
381 static void
382 TdlsCmdKeyInfoDisplay(
383 GLUE_INFO_T *prGlueInfo,
384 UINT_8 *prInBuf,
385 UINT_32 u4InBufLen
386 );
387
388 static void
389 TdlsCmdMibParamUpdate(
390 P_GLUE_INFO_T prGlueInfo,
391 UINT_8 *prInBuf,
392 UINT_32 u4InBufLen
393 );
394
395 static void
396 TdlsCmdSetupConf(
397 P_GLUE_INFO_T prGlueInfo,
398 UINT_8 *prInBuf,
399 UINT_32 u4InBufLen
400 );
401
402 static void
403 TdlsCmdUapsdConf(
404 P_GLUE_INFO_T prGlueInfo,
405 UINT_8 *prInBuf,
406 UINT_32 u4InBufLen
407 );
408
409 static TDLS_STATUS
410 TdlsInfoDisplay(
411 ADAPTER_T *prAdapter,
412 VOID *pvSetBuffer,
413 UINT_32 u4SetBufferLen,
414 UINT_32 *pu4SetInfoLen
415 );
416
417 static TDLS_STATUS
418 TdlsKeyInfoDisplay(
419 ADAPTER_T *prAdapter,
420 VOID *pvSetBuffer,
421 UINT_32 u4SetBufferLen,
422 UINT_32 *pu4SetInfoLen
423 );
424
425 static VOID
426 TdlsLinkHistoryRecord(
427 GLUE_INFO_T *prGlueInfo,
428 BOOLEAN fgIsTearDown,
429 UINT8 *pucPeerMac,
430 BOOLEAN fgIsFromUs,
431 UINT16 u2ReasonCode,
432 VOID *prOthers
433 );
434
435 static VOID
436 TdlsLinkHistoryRecordUpdate(
437 GLUE_INFO_T *prGlueInfo,
438 UINT8 *pucPeerMac,
439 TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus,
440 VOID *pInfo
441 );
442
443 static TDLS_STATUS
444 TdlsMibParamUpdate(
445 ADAPTER_T *prAdapter,
446 VOID *pvSetBuffer,
447 UINT_32 u4SetBufferLen,
448 UINT_32 *pu4SetInfoLen
449 );
450
451 static TDLS_STATUS
452 TdlsSetupConf(
453 ADAPTER_T *prAdapter,
454 VOID *pvSetBuffer,
455 UINT_32 u4SetBufferLen,
456 UINT_32 *pu4SetInfoLen
457 );
458
459 static TDLS_STATUS
460 TdlsUapsdConf(
461 ADAPTER_T *prAdapter,
462 VOID *pvSetBuffer,
463 UINT_32 u4SetBufferLen,
464 UINT_32 *pu4SetInfoLen
465 );
466
467 static void
468 TdlsEventStatistics(
469 GLUE_INFO_T *prGlueInfo,
470 UINT8 *prInBuf,
471 UINT32 u4InBufLen
472 );
473
474 static void
475 TdlsEventTearDown(
476 GLUE_INFO_T *prGlueInfo,
477 UINT8 *prInBuf,
478 UINT32 u4InBufLen
479 );
480
481 #endif /* TDLS_CFG_CMD_TEST */
482
483 /*******************************************************************************
484 * P R I V A T E D A T A
485 ********************************************************************************
486 */
487 static BOOLEAN fgIsPtiTimeoutSkip = FALSE;
488
489
490 /*******************************************************************************
491 * P R I V A T E F U N C T I O N S
492 ********************************************************************************
493 */
494
495 /*----------------------------------------------------------------------------*/
496 /*!
497 * \brief This routine is called to indicate packets to upper layer.
498 *
499 * \param[in] prGlueInfo Pointer to the Adapter structure
500 * \param[in] prSkb A pointer to the received packet
501 *
502 * \retval None
503 *
504 */
505 /*----------------------------------------------------------------------------*/
506 static VOID
507 TdlsCmdTestRxIndicatePkts (
508 GLUE_INFO_T *prGlueInfo,
509 struct sk_buff *prSkb
510 )
511 {
512 struct net_device *prNetDev;
513
514
515 /* init */
516 prNetDev = prGlueInfo->prDevHandler;
517 prGlueInfo->rNetDevStats.rx_bytes += prSkb->len;
518 prGlueInfo->rNetDevStats.rx_packets++;
519
520 /* pass to upper layer */
521 prNetDev->last_rx = jiffies;
522 prSkb->protocol = eth_type_trans(prSkb, prNetDev);
523 prSkb->dev = prNetDev;
524
525 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
526 if(!in_interrupt()){
527 netif_rx_ni(prSkb); /* only in non-interrupt context */
528 }
529 else {
530 netif_rx(prSkb);
531 }
532 #else
533 netif_rx(prSkb);
534 #endif
535 }
536
537
538 #if TDLS_CFG_CMD_TEST
539
540 #define LR_TDLS_FME_FIELD_FILL(__Len) \
541 pPkt += __Len; \
542 u4PktLen += __Len;
543
544 /*----------------------------------------------------------------------------*/
545 /*! \brief This routine is called to add a TDLS peer.
546 *
547 * \param[in] prGlueInfo Pointer to the Adapter structure
548 * \param[in] prInBuf A pointer to the command string buffer
549 * \param[in] u4InBufLen The length of the buffer
550 * \param[out] None
551 *
552 * \retval None
553 *
554 * EX: iwpriv wlan0 set_str_cmd 0_2_[Responder MAC]
555
556 iwpriv wlan0 set_str_cmd 0_2_00:11:22:33:44:01
557 */
558 /*----------------------------------------------------------------------------*/
559 static void
560 TdlsCmdTestAddPeer(
561 P_GLUE_INFO_T prGlueInfo,
562 UINT_8 *prInBuf,
563 UINT_32 u4InBufLen
564 )
565 {
566 PARAM_CUSTOM_TDLS_CMD_STRUC_T rCmd;
567 struct wireless_dev *prWdev;
568
569
570 /* reset */
571 kalMemZero(&rCmd, sizeof(rCmd));
572
573 /* parse arguments */
574 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr);
575
576 /* init */
577 rCmd.rPeerInfo.supported_rates = NULL;
578 rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa;
579 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
580 rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa;
581 #endif
582 rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER);
583
584 /* send command to wifi task to handle */
585 prWdev = prGlueInfo->prDevHandler->ieee80211_ptr;
586 mtk_cfg80211_add_station(\
587 prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo);
588 }
589
590
591 /*----------------------------------------------------------------------------*/
592 /*! \brief This routine is called to simulate to set the TDLS Prohibited bit.
593 *
594 * \param[in] prGlueInfo Pointer to the Adapter structure
595 * \param[in] prInBuf A pointer to the command string buffer
596 * \param[in] u4InBufLen The length of the buffer
597 * \param[out] None
598 *
599 * \retval None
600 *
601 * EX: iwpriv wlan0 set_str_cmd 0_16_[Enable/Disable]_[Set/Clear]
602
603 iwpriv wlan0 set_str_cmd 0_16_1_1
604 */
605 /*----------------------------------------------------------------------------*/
606 static void
607 TdlsCmdTestChSwProhibitedBitSet(
608 P_GLUE_INFO_T prGlueInfo,
609 UINT_8 *prInBuf,
610 UINT_32 u4InBufLen
611 )
612 {
613 extern BOOLEAN flgTdlsTestExtCapElm;
614 extern UINT8 aucTdlsTestExtCapElm[];
615 TDLS_CMD_CORE_T rCmd;
616
617
618 /* parse arguments */
619 kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
620 rCmd.Content.rCmdProhibit.fgIsEnable = \
621 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
622 rCmd.Content.rCmdProhibit.fgIsSet = \
623 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
624
625 DBGLOG(TDLS, INFO, ("%s: fgIsEnable = %d\n",
626 __FUNCTION__, rCmd.Content.rCmdProhibit.fgIsEnable));
627
628 /* command to do this */
629 flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable;
630
631 aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP;
632 aucTdlsTestExtCapElm[1] = 5;
633 aucTdlsTestExtCapElm[2] = 0;
634 aucTdlsTestExtCapElm[3] = 0;
635 aucTdlsTestExtCapElm[4] = 0;
636 aucTdlsTestExtCapElm[5] = 0;
637 aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 7); /* bit39 */
638 }
639
640
641 /*----------------------------------------------------------------------------*/
642 /*! \brief This routine is called to receive a channel switch request from the peer.
643 *
644 * \param[in] prGlueInfo Pointer to the Adapter structure
645 * \param[in] prInBuf A pointer to the command string buffer
646 * \param[in] u4InBufLen The length of the buffer
647 * \param[out] None
648 *
649 * \retval None
650 *
651 * EX: iwpriv wlan0 set_str_cmd 0_1_5_[TDLS Peer MAC]_[Chan]_[RegulatoryClass]_
652 [SecondaryChannelOffset]_[SwitchTime]_[SwitchTimeout]
653
654 iwpriv wlan0 set_str_cmd 0_1_5_00:11:22:33:44:01_1_255_0_15000_30000
655
656 RegulatoryClass: TODO (reference to Annex I of 802.11n spec.)
657 Secondary Channel Offset: 0 (SCN - no secondary channel)
658 1 (SCA - secondary channel above)
659 2 (SCB - secondary channel below)
660 SwitchTime: units of microseconds
661
662 */
663 /*----------------------------------------------------------------------------*/
664 static void
665 TdlsCmdTestChSwReqRecv(
666 P_GLUE_INFO_T prGlueInfo,
667 UINT_8 *prInBuf,
668 UINT_32 u4InBufLen
669 )
670 {
671 WLAN_STATUS rStatus;
672 TDLS_CMD_CORE_T rCmd;
673 UINT_32 u4BufLen;
674
675
676 /* parse arguments */
677 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
678
679 rCmd.Content.rCmdChStReqRcv.u4Chan = \
680 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
681 rCmd.Content.rCmdChStReqRcv.u4RegClass = \
682 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
683 rCmd.Content.rCmdChStReqRcv.u4SecChanOff = \
684 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
685 rCmd.Content.rCmdChStReqRcv.u4SwitchTime = \
686 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
687 rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout = \
688 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
689
690 DBGLOG(TDLS, INFO, ("%s: ["MACSTR"] u4Chan=%u u4RegClass=%u"
691 " u4SecChanOff=%u u4SwitchTime=%u u4SwitchTimeout=%u\n",
692 __FUNCTION__, MAC2STR(rCmd.aucPeerMac),
693 (UINT32)rCmd.Content.rCmdChStReqRcv.u4Chan,
694 (UINT32)rCmd.Content.rCmdChStReqRcv.u4RegClass,
695 (UINT32)rCmd.Content.rCmdChStReqRcv.u4SecChanOff,
696 (UINT32)rCmd.Content.rCmdChStReqRcv.u4SwitchTime,
697 (UINT32)rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout));
698
699 /* command to do this */
700 rStatus = kalIoctl(prGlueInfo,
701 TdlsTestChStReqRecv,
702 &rCmd,
703 sizeof(rCmd),
704 FALSE,
705 FALSE,
706 FALSE,
707 FALSE,
708 &u4BufLen);
709
710 if (rStatus != WLAN_STATUS_SUCCESS)
711 {
712 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
713 return;
714 }
715 }
716
717
718 /*----------------------------------------------------------------------------*/
719 /*! \brief This routine is called to receive a channel switch response from the peer.
720 *
721 * \param[in] prGlueInfo Pointer to the Adapter structure
722 * \param[in] prInBuf A pointer to the command string buffer
723 * \param[in] u4InBufLen The length of the buffer
724 * \param[out] None
725 *
726 * \retval None
727 *
728 * EX: iwpriv wlan0 set_str_cmd 0_1_6_[TDLS Peer MAC]_[Chan]_
729 [SwitchTime]_[SwitchTimeout]_[StatusCode]
730
731 iwpriv wlan0 set_str_cmd 0_1_6_00:11:22:33:44:01_11_15000_30000_0
732
733 RegulatoryClass: TODO (reference to Annex I of 802.11n spec.)
734 Secondary Channel Offset: 0 (SCN - no secondary channel)
735 1 (SCA - secondary channel above)
736 2 (SCB - secondary channel below)
737 SwitchTime: units of microseconds
738
739 */
740 /*----------------------------------------------------------------------------*/
741 static void
742 TdlsCmdTestChSwRspRecv(
743 P_GLUE_INFO_T prGlueInfo,
744 UINT_8 *prInBuf,
745 UINT_32 u4InBufLen
746 )
747 {
748 WLAN_STATUS rStatus;
749 TDLS_CMD_CORE_T rCmd;
750 UINT_32 u4BufLen;
751
752
753 /* parse arguments */
754 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
755
756 rCmd.Content.rCmdChStRspRcv.u4Chan = \
757 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
758 rCmd.Content.rCmdChStRspRcv.u4SwitchTime = \
759 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
760 rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout = \
761 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
762 rCmd.Content.rCmdChStRspRcv.u4StatusCode = \
763 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
764
765 DBGLOG(TDLS, INFO, ("%s: ["MACSTR"] u4Chan=%u "
766 " u4SwitchTime=%u u4SwitchTimeout=%u u4StatusCode=%u\n",
767 __FUNCTION__, MAC2STR(rCmd.aucPeerMac),
768 (UINT32)rCmd.Content.rCmdChStRspRcv.u4Chan,
769 (UINT32)rCmd.Content.rCmdChStRspRcv.u4SwitchTime,
770 (UINT32)rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout,
771 (UINT32)rCmd.Content.rCmdChStRspRcv.u4StatusCode));
772
773 /* command to do this */
774 rStatus = kalIoctl(prGlueInfo,
775 TdlsTestChStRspRecv,
776 &rCmd,
777 sizeof(rCmd),
778 FALSE,
779 FALSE,
780 FALSE,
781 FALSE,
782 &u4BufLen);
783
784 if (rStatus != WLAN_STATUS_SUCCESS)
785 {
786 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
787 return;
788 }
789 }
790
791
792 /*----------------------------------------------------------------------------*/
793 /*! \brief This routine is called to inform firmware to skip channel switch timeout function.
794 *
795 * \param[in] prGlueInfo Pointer to the Adapter structure
796 * \param[in] prInBuf A pointer to the command string buffer
797 * \param[in] u4InBufLen The length of the buffer
798 * \param[out] None
799 *
800 * \retval None
801 *
802 * EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable]
803
804 iwpriv wlan0 set_str_cmd 0_11_1
805 */
806 /*----------------------------------------------------------------------------*/
807 static void
808 TdlsCmdTestChSwTimeoutSkip(
809 P_GLUE_INFO_T prGlueInfo,
810 UINT_8 *prInBuf,
811 UINT_32 u4InBufLen
812 )
813 {
814 WLAN_STATUS rStatus;
815 TDLS_CMD_CORE_T rCmd;
816 UINT_32 u4BufLen;
817
818
819 /* parse arguments */
820 kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
821 rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = \
822 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
823
824 DBGLOG(TDLS, INFO, ("%s: fgIsEnable = %d\n",
825 __FUNCTION__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable));
826
827 /* command to do this */
828 rStatus = kalIoctl(prGlueInfo,
829 TdlsTestChSwTimeoutSkip,
830 &rCmd,
831 sizeof(rCmd),
832 FALSE,
833 FALSE,
834 FALSE,
835 FALSE,
836 &u4BufLen);
837
838 if (rStatus != WLAN_STATUS_SUCCESS)
839 {
840 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
841 return;
842 }
843 }
844
845
846 /*----------------------------------------------------------------------------*/
847 /*! \brief This routine is called to send a data frame to the peer periodically.
848 *
849 * \param[in] prGlueInfo Pointer to the Adapter structure
850 * \param[in] prInBuf A pointer to the command string buffer
851 * \param[in] u4InBufLen The length of the buffer
852 * \param[out] None
853 *
854 * \retval None
855 *
856 */
857 /*----------------------------------------------------------------------------*/
858 static TIMER_T rTdlsTimerTestDataSend;
859 static UINT_8 aucTdlsTestDataSPeerMac[6];
860 static UINT_16 u2TdlsTestDataSInterval;
861
862 static void
863 TdlsCmdTestDataContSend(
864 GLUE_INFO_T *prGlueInfo,
865 UINT_8 *prInBuf,
866 UINT_32 u4InBufLen
867 )
868 {
869 ADAPTER_T *prAdapter;
870 BOOLEAN fgIsEnabled;
871
872
873 /* init */
874 prAdapter = prGlueInfo->prAdapter;
875
876 /* parse arguments */
877 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucTdlsTestDataSPeerMac);
878 u2TdlsTestDataSInterval = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
879 fgIsEnabled = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
880
881 cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend);
882
883 if (fgIsEnabled == FALSE)
884 {
885 /* stop test timer */
886 return;
887 }
888
889 /* re-init test timer */
890 cnmTimerInitTimer(prAdapter,
891 &rTdlsTimerTestDataSend,
892 (PFN_MGMT_TIMEOUT_FUNC)TdlsTimerTestDataContSend,
893 (ULONG)NULL);
894
895 cnmTimerStartTimer(prAdapter,
896 &rTdlsTimerTestDataSend,
897 u2TdlsTestDataSInterval);
898 }
899
900
901 /*----------------------------------------------------------------------------*/
902 /*! \brief This routine is called to receive a data frame from the peer.
903 *
904 * \param[in] prGlueInfo Pointer to the Adapter structure
905 * \param[in] prInBuf A pointer to the command string buffer
906 * \param[in] u4InBufLen The length of the buffer
907 * \param[out] None
908 *
909 * \retval None
910 *
911 * EX: iwpriv wlan0 set_str_cmd 0_0_x80_[TDLS Peer MAC]_[PM]_[UP]_[EOSP]_[IsNull]
912
913 iwpriv wlan0 set_str_cmd 0_1_x80_00:11:22:33:44:01_0_0_0_0
914 */
915 /*----------------------------------------------------------------------------*/
916 static void
917 TdlsCmdTestDataRecv(
918 P_GLUE_INFO_T prGlueInfo,
919 UINT_8 *prInBuf,
920 UINT_32 u4InBufLen
921 )
922 {
923 WLAN_STATUS rStatus;
924 TDLS_CMD_CORE_T rCmd;
925 UINT_32 u4BufLen;
926
927
928 /* parse arguments */
929 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
930 rCmd.Content.rCmdDatRcv.u4PM = \
931 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
932 rCmd.Content.rCmdDatRcv.u4UP = \
933 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
934 rCmd.Content.rCmdDatRcv.u4EOSP = \
935 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
936 rCmd.Content.rCmdDatRcv.u4IsNull = \
937 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
938
939 DBGLOG(TDLS, INFO,
940 ("<tdls_cmd> %s: ["MACSTR"] PM(%u) UP(%u) EOSP(%u) NULL(%u)\n",
941 __FUNCTION__, MAC2STR(rCmd.aucPeerMac),
942 (UINT32)rCmd.Content.rCmdDatRcv.u4PM,
943 (UINT32)rCmd.Content.rCmdDatRcv.u4UP,
944 (UINT32)rCmd.Content.rCmdDatRcv.u4EOSP,
945 (UINT32)rCmd.Content.rCmdDatRcv.u4IsNull));
946
947 /* command to do this */
948 rStatus = kalIoctl(prGlueInfo,
949 TdlsTestDataRecv,
950 &rCmd,
951 sizeof(rCmd),
952 FALSE,
953 FALSE,
954 FALSE,
955 FALSE,
956 &u4BufLen);
957
958 if (rStatus != WLAN_STATUS_SUCCESS)
959 {
960 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
961 return;
962 }
963 }
964
965
966 /*----------------------------------------------------------------------------*/
967 /*! \brief This routine is called to send a data frame to the peer.
968 *
969 * \param[in] prGlueInfo Pointer to the Adapter structure
970 * \param[in] prInBuf A pointer to the command string buffer
971 * \param[in] u4InBufLen The length of the buffer
972 * \param[out] None
973 *
974 * \retval None
975 *
976 * EX: iwpriv wlan0 set_str_cmd 0_4_[Responder MAC]_[tx status]
977
978 iwpriv wlan0 set_str_cmd 0_4_00:11:22:33:44:01_0
979 */
980 /*----------------------------------------------------------------------------*/
981 static void
982 TdlsCmdTestDataSend(
983 P_GLUE_INFO_T prGlueInfo,
984 UINT_8 *prInBuf,
985 UINT_32 u4InBufLen
986 )
987 {
988 P_ADAPTER_T prAdapter;
989 struct sk_buff *prMsduInfo;
990 UINT_8 *prPkt;
991 UINT_8 MAC[6];
992 UINT_8 ucTxStatus;
993
994
995 /* init */
996 prAdapter = prGlueInfo->prAdapter;
997
998 /* parse arguments */
999 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, MAC);
1000 ucTxStatus = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1001
1002 /* allocate a data frame */
1003 prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt);
1004 if (prMsduInfo == NULL)
1005 {
1006 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s allocate pkt fail!\n",
1007 __FUNCTION__));
1008 return;
1009 }
1010
1011 /* init dev */
1012 prMsduInfo->dev = prGlueInfo->prDevHandler;
1013 if (prMsduInfo->dev == NULL)
1014 {
1015 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s prMsduInfo->dev == NULL!\n",
1016 __FUNCTION__));
1017 kalPacketFree(prGlueInfo, prMsduInfo);
1018 return;
1019 }
1020
1021 /* init packet */
1022 prMsduInfo->len = 1000;
1023 kalMemZero(prMsduInfo->data, 100); /* for QoS field */
1024 kalMemCopy(prMsduInfo->data, MAC, 6);
1025 kalMemCopy(prMsduInfo->data+6, prAdapter->rMyMacAddr, 6);
1026 *(UINT_16 *)(prMsduInfo->data+12) = 0x0800;
1027
1028 /* simulate OS to send the packet */
1029 wlanHardStartXmit(prMsduInfo, prMsduInfo->dev);
1030 }
1031
1032
1033 /*----------------------------------------------------------------------------*/
1034 /*! \brief This routine is called to simulate to set the TDLS Prohibited bit.
1035 *
1036 * \param[in] prGlueInfo Pointer to the Adapter structure
1037 * \param[in] prInBuf A pointer to the command string buffer
1038 * \param[in] u4InBufLen The length of the buffer
1039 * \param[out] None
1040 *
1041 * \retval None
1042 *
1043 * EX: iwpriv wlan0 set_str_cmd 0_16_[mili seconds]
1044
1045 iwpriv wlan0 set_str_cmd 0_19_1000
1046 */
1047 /*----------------------------------------------------------------------------*/
1048 static void
1049 TdlsCmdTestDelay(
1050 P_GLUE_INFO_T prGlueInfo,
1051 UINT_8 *prInBuf,
1052 UINT_32 u4InBufLen
1053 )
1054 {
1055 UINT32 u4Delay;
1056
1057
1058 u4Delay = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1059 DBGLOG(TDLS, INFO, ("%s: Delay = %d\n",
1060 __FUNCTION__, u4Delay));
1061
1062 kalMdelay(u4Delay);
1063 }
1064
1065
1066 /*----------------------------------------------------------------------------*/
1067 /*! \brief This routine is called to receive a test discovery request frame command.
1068 *
1069 * \param[in] prGlueInfo Pointer to the Adapter structure
1070 * \param[in] prInBuf A pointer to the command string buffer
1071 * \param[in] u4InBufLen The length of the buffer
1072 * \param[out] None
1073 *
1074 * \retval None
1075 *
1076 * EX: iwpriv wlan0 set_str_cmd 0_1_10_[DialogToken]_[Peer MAC]_[BSSID]
1077
1078 iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01
1079 iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01_00:22:33:44:11:22
1080 */
1081 /*----------------------------------------------------------------------------*/
1082 static void
1083 TdlsCmdTestDiscoveryReqRecv(
1084 GLUE_INFO_T *prGlueInfo,
1085 UINT_8 *prInBuf,
1086 UINT_32 u4InBufLen
1087 )
1088 {
1089 ADAPTER_T *prAdapter;
1090 P_BSS_INFO_T prBssInfo;
1091 struct sk_buff *prMsduInfo;
1092 UINT_8 *pPkt;
1093 UINT_32 u4PktLen, u4IeLen;
1094 UINT_8 ucDialogToken, aucPeerMac[6], aucBSSID[6], aucZeroMac[6];
1095
1096
1097 /* parse arguments */
1098 ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1099 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
1100
1101 kalMemZero(aucZeroMac, sizeof(aucZeroMac));
1102 kalMemZero(aucBSSID, sizeof(aucBSSID));
1103 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID);
1104
1105 DBGLOG(TDLS, INFO,
1106 ("<tdls_fme> %s: DialogToken=%d from "MACSTR"\n",
1107 __FUNCTION__, ucDialogToken, MAC2STR(aucPeerMac)));
1108
1109 /* allocate/init packet */
1110 prAdapter = prGlueInfo->prAdapter;
1111 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
1112 u4PktLen = 0;
1113
1114 prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
1115 if (prMsduInfo == NULL) {
1116 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: allocate pkt fail\n", __FUNCTION__));
1117 return;
1118 }
1119
1120 prMsduInfo->dev = prGlueInfo->prDevHandler;
1121 if (prMsduInfo->dev == NULL)
1122 {
1123 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: MsduInfo->dev == NULL\n", __FUNCTION__));
1124 kalPacketFree(prGlueInfo, prMsduInfo);
1125 return;
1126 }
1127
1128 /* make up frame content */
1129 /* 1. 802.3 header */
1130 kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
1131 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
1132 kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
1133 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
1134 *(UINT_16 *)pPkt = htons(TDLS_FRM_PROT_TYPE);
1135 LR_TDLS_FME_FIELD_FILL(2);
1136
1137 /* 2. payload type */
1138 *pPkt = TDLS_FRM_PAYLOAD_TYPE;
1139 LR_TDLS_FME_FIELD_FILL(1);
1140
1141 /* 3. Frame Formation - (1) Category */
1142 *pPkt = TDLS_FRM_CATEGORY;
1143 LR_TDLS_FME_FIELD_FILL(1);
1144
1145 /* 3. Frame Formation - (2) Action */
1146 *pPkt = TDLS_FRM_ACTION_DISCOVERY_REQ;
1147 LR_TDLS_FME_FIELD_FILL(1);
1148
1149 /* 3. Frame Formation - (3) Dialog token */
1150 *pPkt = ucDialogToken;
1151 LR_TDLS_FME_FIELD_FILL(1);
1152
1153 /* 3. Frame Formation - (16) Link identifier element */
1154 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
1155 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18;
1156
1157 if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0)
1158 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
1159 else
1160 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6);
1161
1162 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6);
1163 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6);
1164
1165 u4IeLen = IE_SIZE(pPkt);
1166 LR_TDLS_FME_FIELD_FILL(u4IeLen);
1167
1168 /* 4. Update packet length */
1169 prMsduInfo->len = u4PktLen;
1170 dumpMemory8(ANDROID_LOG_INFO, prMsduInfo->data, u4PktLen);
1171
1172 /* pass to OS */
1173 TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
1174 }
1175
1176
1177 /*----------------------------------------------------------------------------*/
1178 /*! \brief This routine is called to inform firmware to skip keep alive function.
1179 *
1180 * \param[in] prGlueInfo Pointer to the Adapter structure
1181 * \param[in] prInBuf A pointer to the command string buffer
1182 * \param[in] u4InBufLen The length of the buffer
1183 * \param[out] None
1184 *
1185 * \retval None
1186 *
1187 * EX: iwpriv wlan0 set_str_cmd 0_10_[Enable/Disable]
1188
1189 iwpriv wlan0 set_str_cmd 0_10_1
1190 */
1191 /*----------------------------------------------------------------------------*/
1192 static void
1193 TdlsCmdTestKeepAliveSkip(
1194 P_GLUE_INFO_T prGlueInfo,
1195 UINT_8 *prInBuf,
1196 UINT_32 u4InBufLen
1197 )
1198 {
1199 WLAN_STATUS rStatus;
1200 TDLS_CMD_CORE_T rCmd;
1201 UINT_32 u4BufLen;
1202
1203
1204 /* parse arguments */
1205 kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
1206 rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = \
1207 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1208
1209 DBGLOG(TDLS, INFO, ("%s: fgIsEnable = %d\n",
1210 __FUNCTION__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable));
1211
1212 /* command to do this */
1213 rStatus = kalIoctl(prGlueInfo,
1214 TdlsTestKeepAliveSkip,
1215 &rCmd,
1216 sizeof(rCmd),
1217 FALSE,
1218 FALSE,
1219 FALSE,
1220 FALSE,
1221 &u4BufLen);
1222
1223 if (rStatus != WLAN_STATUS_SUCCESS)
1224 {
1225 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
1226 return;
1227 }
1228 }
1229
1230
1231 /*----------------------------------------------------------------------------*/
1232 /*! \brief This routine is called to simulate to set the TDLS Prohibited bit.
1233 *
1234 * \param[in] prGlueInfo Pointer to the Adapter structure
1235 * \param[in] prInBuf A pointer to the command string buffer
1236 * \param[in] u4InBufLen The length of the buffer
1237 * \param[out] None
1238 *
1239 * \retval None
1240 *
1241 * EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable]_[Set/Clear]
1242
1243 iwpriv wlan0 set_str_cmd 0_13_1_1
1244 */
1245 /*----------------------------------------------------------------------------*/
1246 static void
1247 TdlsCmdTestProhibitedBitSet(
1248 P_GLUE_INFO_T prGlueInfo,
1249 UINT_8 *prInBuf,
1250 UINT_32 u4InBufLen
1251 )
1252 {
1253 extern BOOLEAN flgTdlsTestExtCapElm;
1254 extern UINT8 aucTdlsTestExtCapElm[];
1255 TDLS_CMD_CORE_T rCmd;
1256
1257
1258 /* parse arguments */
1259 kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
1260 rCmd.Content.rCmdProhibit.fgIsEnable = \
1261 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1262 rCmd.Content.rCmdProhibit.fgIsSet = \
1263 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1264
1265 DBGLOG(TDLS, INFO, ("%s: fgIsEnable = %d\n",
1266 __FUNCTION__, rCmd.Content.rCmdProhibit.fgIsEnable));
1267
1268 /* command to do this */
1269 flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable;
1270
1271 aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP;
1272 aucTdlsTestExtCapElm[1] = 5;
1273 aucTdlsTestExtCapElm[2] = 0;
1274 aucTdlsTestExtCapElm[3] = 0;
1275 aucTdlsTestExtCapElm[4] = 0;
1276 aucTdlsTestExtCapElm[5] = 0;
1277 aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 6); /* bit38 */
1278 }
1279
1280
1281 /*----------------------------------------------------------------------------*/
1282 /*! \brief This routine is called to receive a PTI request from the AP.
1283 *
1284 * \param[in] prGlueInfo Pointer to the Adapter structure
1285 * \param[in] prInBuf A pointer to the command string buffer
1286 * \param[in] u4InBufLen The length of the buffer
1287 * \param[out] None
1288 *
1289 * \retval None
1290 *
1291 * EX: iwpriv wlan0 set_str_cmd 0_1_4_[TDLS Peer MAC]_[Dialog Token]
1292
1293 iwpriv wlan0 set_str_cmd 0_1_4_00:11:22:33:44:01_0
1294 */
1295 /*----------------------------------------------------------------------------*/
1296 static void
1297 TdlsCmdTestPtiReqRecv(
1298 P_GLUE_INFO_T prGlueInfo,
1299 UINT_8 *prInBuf,
1300 UINT_32 u4InBufLen
1301 )
1302 {
1303 WLAN_STATUS rStatus;
1304 TDLS_CMD_CORE_T rCmd;
1305 UINT_32 u4BufLen;
1306
1307
1308 /* parse arguments */
1309 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
1310
1311 rCmd.Content.rCmdPtiRspRcv.u4DialogToken = \
1312 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1313
1314 DBGLOG(TDLS, INFO, ("%s: ["MACSTR"] u4DialogToken = %u\n",
1315 __FUNCTION__, MAC2STR(rCmd.aucPeerMac),
1316 (UINT32)rCmd.Content.rCmdPtiRspRcv.u4DialogToken));
1317
1318 /* command to do this */
1319 rStatus = kalIoctl(prGlueInfo,
1320 TdlsTestPtiReqRecv,
1321 &rCmd,
1322 sizeof(rCmd),
1323 FALSE,
1324 FALSE,
1325 FALSE,
1326 FALSE,
1327 &u4BufLen);
1328
1329 if (rStatus != WLAN_STATUS_SUCCESS)
1330 {
1331 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
1332 return;
1333 }
1334 }
1335
1336
1337 /*----------------------------------------------------------------------------*/
1338 /*! \brief This routine is called to receive a PTI response from the peer.
1339 *
1340 * \param[in] prGlueInfo Pointer to the Adapter structure
1341 * \param[in] prInBuf A pointer to the command string buffer
1342 * \param[in] u4InBufLen The length of the buffer
1343 * \param[out] None
1344 *
1345 * \retval None
1346 *
1347 * EX: iwpriv wlan0 set_str_cmd 0_1_9_[TDLS Peer MAC]_[Dialog Token]_[PM]
1348
1349 iwpriv wlan0 set_str_cmd 0_1_9_00:11:22:33:44:01_0_1
1350 */
1351 /*----------------------------------------------------------------------------*/
1352 static void
1353 TdlsCmdTestPtiRspRecv(
1354 P_GLUE_INFO_T prGlueInfo,
1355 UINT_8 *prInBuf,
1356 UINT_32 u4InBufLen
1357 )
1358 {
1359 WLAN_STATUS rStatus;
1360 TDLS_CMD_CORE_T rCmd;
1361 UINT_32 u4BufLen;
1362
1363
1364 /* parse arguments */
1365 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
1366
1367 rCmd.Content.rCmdPtiRspRcv.u4DialogToken = \
1368 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1369 rCmd.Content.rCmdPtiRspRcv.u4PM = \
1370 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1371
1372 DBGLOG(TDLS, INFO, ("%s: ["MACSTR"] u4DialogToken = %u %u\n",
1373 __FUNCTION__, MAC2STR(rCmd.aucPeerMac),
1374 (UINT32)rCmd.Content.rCmdPtiRspRcv.u4DialogToken,
1375 (UINT32)rCmd.Content.rCmdPtiRspRcv.u4PM));
1376
1377 /* command to do this */
1378 rStatus = kalIoctl(prGlueInfo,
1379 TdlsTestPtiRspRecv,
1380 &rCmd,
1381 sizeof(rCmd),
1382 FALSE,
1383 FALSE,
1384 FALSE,
1385 FALSE,
1386 &u4BufLen);
1387
1388 if (rStatus != WLAN_STATUS_SUCCESS)
1389 {
1390 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
1391 return;
1392 }
1393 }
1394
1395
1396 /*----------------------------------------------------------------------------*/
1397 /*! \brief This routine is called to inform firmware to simulate PTI tx done fail case.
1398 *
1399 * \param[in] prGlueInfo Pointer to the Adapter structure
1400 * \param[in] prInBuf A pointer to the command string buffer
1401 * \param[in] u4InBufLen The length of the buffer
1402 * \param[out] None
1403 *
1404 * \retval None
1405 *
1406 * EX: iwpriv wlan0 set_str_cmd 0_21_[Enable/Disable]
1407
1408 iwpriv wlan0 set_str_cmd 0_21_1
1409 */
1410 /*----------------------------------------------------------------------------*/
1411 static void
1412 TdlsCmdTestPtiTxDoneFail(
1413 P_GLUE_INFO_T prGlueInfo,
1414 UINT_8 *prInBuf,
1415 UINT_32 u4InBufLen
1416 )
1417 {
1418 WLAN_STATUS rStatus;
1419 TDLS_CMD_CORE_T rCmd;
1420 UINT_32 u4BufLen;
1421
1422
1423 /* parse arguments */
1424 kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
1425 rCmd.Content.rCmdPtiTxFail.fgIsEnable = \
1426 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1427
1428 DBGLOG(TDLS, INFO, ("%s: fgIsEnable = %d\n",
1429 __FUNCTION__, rCmd.Content.rCmdPtiTxFail.fgIsEnable));
1430
1431 /* command to do this */
1432 rStatus = kalIoctl(prGlueInfo,
1433 TdlsTestPtiTxFail,
1434 &rCmd,
1435 sizeof(rCmd),
1436 FALSE,
1437 FALSE,
1438 FALSE,
1439 FALSE,
1440 &u4BufLen);
1441
1442 if (rStatus != WLAN_STATUS_SUCCESS)
1443 {
1444 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
1445 return;
1446 }
1447 }
1448
1449
1450 /*----------------------------------------------------------------------------*/
1451 /*! \brief This routine is called to receive a test frame.
1452 *
1453 * \param[in] prGlueInfo Pointer to the Adapter structure
1454 * \param[in] prInBuf A pointer to the command string buffer
1455 * \param[in] u4InBufLen The length of the buffer
1456 * \param[out] None
1457 *
1458 * \retval None
1459 *
1460 */
1461 /*----------------------------------------------------------------------------*/
1462 static void
1463 TdlsCmdTestRvFrame(
1464 P_GLUE_INFO_T prGlueInfo,
1465 UINT_8 *prInBuf,
1466 UINT_32 u4InBufLen
1467 )
1468 {
1469 // PARAM_CUSTOM_TDLS_CMD_STRUC_T rCmd;
1470 // TDLS_STATUS u4Status;
1471 UINT_32 u4Subcmd;
1472 // UINT_32 u4BufLen;
1473
1474
1475 /* parse sub-command */
1476 u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1477 DBGLOG(TDLS, INFO, ("<tdls_cmd> test rv frame sub command = %u\n",
1478 (UINT32)u4Subcmd));
1479
1480 /* parse command arguments */
1481 switch(u4Subcmd)
1482 {
1483 case TDLS_FRM_ACTION_SETUP_REQ:
1484 /* simulate to receive a setup request frame */
1485 TdlsCmdTestSetupReqRecv(prGlueInfo, prInBuf, u4InBufLen);
1486 break;
1487
1488 case TDLS_FRM_ACTION_SETUP_RSP:
1489 /* simulate to receive a setup response frame */
1490 TdlsCmdTestSetupRspRecv(prGlueInfo, prInBuf, u4InBufLen);
1491 break;
1492
1493 case TDLS_FRM_ACTION_CONFIRM:
1494 /* simulate to receive a setup confirm frame */
1495 TdlsCmdTestSetupConfirmRecv(prGlueInfo, prInBuf, u4InBufLen);
1496 break;
1497
1498 case TDLS_FRM_ACTION_TEARDOWN:
1499 /* simulate to receive a tear down frame */
1500 TdlsCmdTestTearDownRecv(prGlueInfo, prInBuf, u4InBufLen);
1501 break;
1502
1503 case TDLS_FRM_ACTION_PTI:
1504 /* simulate to receive a PTI request frame */
1505 TdlsCmdTestPtiReqRecv(prGlueInfo, prInBuf, u4InBufLen);
1506 break;
1507
1508 case TDLS_FRM_ACTION_PTI_RSP:
1509 /* simulate to receive a PTI response frame */
1510 TdlsCmdTestPtiRspRecv(prGlueInfo, prInBuf, u4InBufLen);
1511 break;
1512
1513 case TDLS_FRM_DATA_TEST_DATA:
1514 /* simulate to receive a DATA frame */
1515 TdlsCmdTestDataRecv(prGlueInfo, prInBuf, u4InBufLen);
1516 break;
1517
1518 case TDLS_FRM_ACTION_CHAN_SWITCH_REQ:
1519 /* simulate to receive a channel switch request frame */
1520 TdlsCmdTestChSwReqRecv(prGlueInfo, prInBuf, u4InBufLen);
1521 break;
1522
1523 case TDLS_FRM_ACTION_CHAN_SWITCH_RSP:
1524 /* simulate to receive a channel switch response frame */
1525 TdlsCmdTestChSwRspRecv(prGlueInfo, prInBuf, u4InBufLen);
1526 break;
1527
1528 case TDLS_FRM_ACTION_DISCOVERY_REQ:
1529 /* simulate to receive a discovery request frame */
1530 TdlsCmdTestDiscoveryReqRecv(prGlueInfo, prInBuf, u4InBufLen);
1531 break;
1532
1533 default:
1534 DBGLOG(TDLS, ERROR, ("<tdls_cmd> wrong test rv frame sub command\n"));
1535 return;
1536 }
1537
1538 // if (u4Status != TDLS_STATUS_SUCCESS)
1539 {
1540 // DBGLOG(TDLS, ERROR, ("<tdls_cmd> command parse fail\n"));
1541 // return;
1542 }
1543
1544 /* send command to wifi task to handle */
1545 #if 0
1546 kalIoctl(prGlueInfo,
1547 TdlsTestFrameSend,
1548 (PVOID)&rCmd,
1549 sizeof(PARAM_CUSTOM_TDLS_CMD_STRUC_T),
1550 FALSE,
1551 FALSE,
1552 TRUE,
1553 FALSE,
1554 &u4BufLen);
1555 #endif
1556 }
1557
1558
1559 /*----------------------------------------------------------------------------*/
1560 /*! \brief This routine is called to receive a test setup confirm frame command.
1561 *
1562 * \param[in] prGlueInfo Pointer to the Adapter structure
1563 * \param[in] prInBuf A pointer to the command string buffer
1564 * \param[in] u4InBufLen The length of the buffer
1565 * \param[out] None
1566 *
1567 * \retval None
1568 *
1569 * EX: iwpriv wlan0 set_str_cmd 0_1_2_[DialogToken]_[StatusCode]_[Peer MAC]
1570
1571 iwpriv wlan0 set_str_cmd 0_1_2_1_0_00:11:22:33:44:01
1572 */
1573 /*----------------------------------------------------------------------------*/
1574 static void
1575 TdlsCmdTestSetupConfirmRecv(
1576 GLUE_INFO_T *prGlueInfo,
1577 UINT_8 *prInBuf,
1578 UINT_32 u4InBufLen
1579 )
1580 {
1581 ADAPTER_T *prAdapter;
1582 P_BSS_INFO_T prBssInfo;
1583 PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo;
1584 struct sk_buff *prMsduInfo;
1585 UINT_8 *pPkt;
1586 UINT_32 u4PktLen, u4IeLen;
1587 UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6];
1588
1589
1590 /* parse arguments */
1591 ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1592 ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1593 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
1594
1595 DBGLOG(TDLS, INFO,
1596 ("<tdls_fme> %s: DialogToken=%d StatusCode=%d from "MACSTR"\n",
1597 __FUNCTION__, ucDialogToken, ucStatusCode, MAC2STR(aucPeerMac)));
1598
1599 /* allocate/init packet */
1600 prAdapter = prGlueInfo->prAdapter;
1601 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
1602 prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo;
1603 u4PktLen = 0;
1604
1605 prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
1606 if (prMsduInfo == NULL) {
1607 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: allocate pkt fail\n", __FUNCTION__));
1608 return;
1609 }
1610
1611 prMsduInfo->dev = prGlueInfo->prDevHandler;
1612 if (prMsduInfo->dev == NULL)
1613 {
1614 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: MsduInfo->dev == NULL\n", __FUNCTION__));
1615 kalPacketFree(prGlueInfo, prMsduInfo);
1616 return;
1617 }
1618
1619 /* make up frame content */
1620 /* 1. 802.3 header */
1621 kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
1622 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
1623 kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
1624 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
1625 *(UINT_16 *)pPkt = htons(TDLS_FRM_PROT_TYPE);
1626 LR_TDLS_FME_FIELD_FILL(2);
1627
1628 /* 2. payload type */
1629 *pPkt = TDLS_FRM_PAYLOAD_TYPE;
1630 LR_TDLS_FME_FIELD_FILL(1);
1631
1632 /* 3. Frame Formation - (1) Category */
1633 *pPkt = TDLS_FRM_CATEGORY;
1634 LR_TDLS_FME_FIELD_FILL(1);
1635
1636 /* 3. Frame Formation - (2) Action */
1637 *pPkt = TDLS_FRM_ACTION_CONFIRM;
1638 LR_TDLS_FME_FIELD_FILL(1);
1639
1640 /* 3. Frame Formation - (3) Status Code */
1641 *pPkt = ucStatusCode;
1642 *(pPkt+1) = 0x00;
1643 LR_TDLS_FME_FIELD_FILL(2);
1644
1645 /* 3. Frame Formation - (4) Dialog token */
1646 *pPkt = ucDialogToken;
1647 LR_TDLS_FME_FIELD_FILL(1);
1648
1649 /* 3. Frame Formation - (17) WMM Information element */
1650 if (prAdapter->rWifiVar.fgSupportQoS)
1651 {
1652 u4IeLen = mqmGenerateWmmParamIEByParam(\
1653 prAdapter, prBssInfo, pPkt);
1654 LR_TDLS_FME_FIELD_FILL(u4IeLen);
1655 }
1656
1657 /* 3. Frame Formation - (16) Link identifier element */
1658 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
1659 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER;
1660
1661 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
1662 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6);
1663 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6);
1664
1665 u4IeLen = IE_SIZE(pPkt);
1666 LR_TDLS_FME_FIELD_FILL(u4IeLen);
1667
1668 /* 4. Update packet length */
1669 prMsduInfo->len = u4PktLen;
1670 dumpMemory8(ANDROID_LOG_INFO, prMsduInfo->data, u4PktLen);
1671
1672 /* pass to OS */
1673 TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
1674 }
1675
1676
1677 /*----------------------------------------------------------------------------*/
1678 /*! \brief This routine is called to receive a test setup request frame command.
1679 *
1680 * \param[in] prGlueInfo Pointer to the Adapter structure
1681 * \param[in] prInBuf A pointer to the command string buffer
1682 * \param[in] u4InBufLen The length of the buffer
1683 * \param[out] None
1684 *
1685 * \retval None
1686 *
1687 * EX: iwpriv wlan0 set_str_cmd 0_1_0_[DialogToken]_[Peer MAC]_[BSSID]
1688
1689 iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01
1690 iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01_00:22:33:44:11:22
1691 */
1692 /*----------------------------------------------------------------------------*/
1693 static void
1694 TdlsCmdTestSetupReqRecv(
1695 GLUE_INFO_T *prGlueInfo,
1696 UINT_8 *prInBuf,
1697 UINT_32 u4InBufLen
1698 )
1699 {
1700 ADAPTER_T *prAdapter;
1701 P_BSS_INFO_T prBssInfo;
1702 struct sk_buff *prMsduInfo;
1703 UINT_8 *pPkt;
1704 UINT_32 u4PktLen, u4IeLen;
1705 UINT_8 ucDialogToken, aucPeerMac[6], aucBSSID[6], aucZeroMac[6];
1706 UINT_16 u2CapInfo;
1707
1708
1709 /* parse arguments */
1710 ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1711 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
1712
1713 kalMemZero(aucZeroMac, sizeof(aucZeroMac));
1714 kalMemZero(aucBSSID, sizeof(aucBSSID));
1715 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID);
1716
1717 DBGLOG(TDLS, INFO,
1718 ("<tdls_fme> %s: DialogToken=%d from "MACSTR"\n",
1719 __FUNCTION__, ucDialogToken, MAC2STR(aucPeerMac)));
1720
1721 /* allocate/init packet */
1722 prAdapter = prGlueInfo->prAdapter;
1723 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
1724 u4PktLen = 0;
1725
1726 prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
1727 if (prMsduInfo == NULL) {
1728 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: allocate pkt fail\n", __FUNCTION__));
1729 return;
1730 }
1731
1732 prMsduInfo->dev = prGlueInfo->prDevHandler;
1733 if (prMsduInfo->dev == NULL)
1734 {
1735 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: MsduInfo->dev == NULL\n", __FUNCTION__));
1736 kalPacketFree(prGlueInfo, prMsduInfo);
1737 return;
1738 }
1739
1740 /* make up frame content */
1741 /* 1. 802.3 header */
1742 kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
1743 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
1744 kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
1745 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
1746 *(UINT_16 *)pPkt = htons(TDLS_FRM_PROT_TYPE);
1747 LR_TDLS_FME_FIELD_FILL(2);
1748
1749 /* 2. payload type */
1750 *pPkt = TDLS_FRM_PAYLOAD_TYPE;
1751 LR_TDLS_FME_FIELD_FILL(1);
1752
1753 /* 3. Frame Formation - (1) Category */
1754 *pPkt = TDLS_FRM_CATEGORY;
1755 LR_TDLS_FME_FIELD_FILL(1);
1756
1757 /* 3. Frame Formation - (2) Action */
1758 *pPkt = TDLS_FRM_ACTION_SETUP_REQ;
1759 LR_TDLS_FME_FIELD_FILL(1);
1760
1761 /* 3. Frame Formation - (3) Dialog token */
1762 *pPkt = ucDialogToken;
1763 LR_TDLS_FME_FIELD_FILL(1);
1764
1765 /* 3. Frame Formation - (4) Capability */
1766 u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL);
1767 WLAN_SET_FIELD_16(pPkt, u2CapInfo);
1768 LR_TDLS_FME_FIELD_FILL(2);
1769
1770 /* 4. Append general IEs */
1771 u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt);
1772 LR_TDLS_FME_FIELD_FILL(u4IeLen);
1773
1774 /* 3. Frame Formation - (10) Extended capabilities element */
1775 EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP;
1776 EXT_CAP_IE(pPkt)->ucLength = 5;
1777
1778 EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */
1779 EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */
1780 EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */
1781 EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */
1782 EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */
1783
1784 /* TDLS_EX_CAP_PEER_UAPSD */
1785 EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28-24));
1786 /* TDLS_EX_CAP_CHAN_SWITCH */
1787 EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30-24));
1788 /* TDLS_EX_CAP_TDLS */
1789 EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37-32));
1790
1791 u4IeLen = IE_SIZE(pPkt);
1792 LR_TDLS_FME_FIELD_FILL(u4IeLen);
1793
1794 /* 3. Frame Formation - (16) Link identifier element */
1795 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
1796 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18;
1797
1798 if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0)
1799 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
1800 else
1801 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6);
1802
1803 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6);
1804 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6);
1805
1806 u4IeLen = IE_SIZE(pPkt);
1807 LR_TDLS_FME_FIELD_FILL(u4IeLen);
1808
1809 /* 4. Update packet length */
1810 prMsduInfo->len = u4PktLen;
1811 dumpMemory8(ANDROID_LOG_INFO, prMsduInfo->data, u4PktLen);
1812
1813 /* pass to OS */
1814 TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
1815 }
1816
1817
1818 /*----------------------------------------------------------------------------*/
1819 /*! \brief This routine is called to receive a test setup response frame command.
1820 *
1821 * \param[in] prGlueInfo Pointer to the Adapter structure
1822 * \param[in] prInBuf A pointer to the command string buffer
1823 * \param[in] u4InBufLen The length of the buffer
1824 * \param[out] None
1825 *
1826 * \retval None
1827 *
1828 * EX: iwpriv wlan0 set_str_cmd 0_1_1_[DialogToken]_[StatusCode]_[Peer MAC]
1829
1830 iwpriv wlan0 set_str_cmd 0_1_1_1_0_00:11:22:33:44:01
1831 */
1832 /*----------------------------------------------------------------------------*/
1833 static void
1834 TdlsCmdTestSetupRspRecv(
1835 GLUE_INFO_T *prGlueInfo,
1836 UINT_8 *prInBuf,
1837 UINT_32 u4InBufLen
1838 )
1839 {
1840 ADAPTER_T *prAdapter;
1841 P_BSS_INFO_T prBssInfo;
1842 struct sk_buff *prMsduInfo;
1843 UINT_8 *pPkt;
1844 UINT_32 u4PktLen, u4IeLen;
1845 UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6];
1846 UINT_16 u2CapInfo;
1847
1848
1849 /* parse arguments */
1850 ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1851 ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1852 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
1853
1854 DBGLOG(TDLS, INFO,
1855 ("<tdls_fme> %s: DialogToken=%d StatusCode=%d from "MACSTR"\n",
1856 __FUNCTION__, ucDialogToken, ucStatusCode, MAC2STR(aucPeerMac)));
1857
1858 /* allocate/init packet */
1859 prAdapter = prGlueInfo->prAdapter;
1860 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
1861 u4PktLen = 0;
1862
1863 prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
1864 if (prMsduInfo == NULL) {
1865 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: allocate pkt fail\n", __FUNCTION__));
1866 return;
1867 }
1868
1869 prMsduInfo->dev = prGlueInfo->prDevHandler;
1870 if (prMsduInfo->dev == NULL)
1871 {
1872 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: MsduInfo->dev == NULL\n", __FUNCTION__));
1873 kalPacketFree(prGlueInfo, prMsduInfo);
1874 return;
1875 }
1876
1877 /* make up frame content */
1878 /* 1. 802.3 header */
1879 kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
1880 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
1881 kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
1882 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
1883 *(UINT_16 *)pPkt = htons(TDLS_FRM_PROT_TYPE);
1884 LR_TDLS_FME_FIELD_FILL(2);
1885
1886 /* 2. payload type */
1887 *pPkt = TDLS_FRM_PAYLOAD_TYPE;
1888 LR_TDLS_FME_FIELD_FILL(1);
1889
1890 /* 3. Frame Formation - (1) Category */
1891 *pPkt = TDLS_FRM_CATEGORY;
1892 LR_TDLS_FME_FIELD_FILL(1);
1893
1894 /* 3. Frame Formation - (2) Action */
1895 *pPkt = TDLS_FRM_ACTION_SETUP_RSP;
1896 LR_TDLS_FME_FIELD_FILL(1);
1897
1898 /* 3. Frame Formation - (3) Status Code */
1899 *pPkt = ucStatusCode;
1900 *(pPkt+1) = 0x00;
1901 LR_TDLS_FME_FIELD_FILL(2);
1902
1903 /* 3. Frame Formation - (4) Dialog token */
1904 *pPkt = ucDialogToken;
1905 LR_TDLS_FME_FIELD_FILL(1);
1906
1907 /* 3. Frame Formation - (5) Capability */
1908 u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL);
1909 WLAN_SET_FIELD_16(pPkt, u2CapInfo);
1910 LR_TDLS_FME_FIELD_FILL(2);
1911
1912 /* 4. Append general IEs */
1913 u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt);
1914 LR_TDLS_FME_FIELD_FILL(u4IeLen);
1915
1916 /* 3. Frame Formation - (10) Extended capabilities element */
1917 EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP;
1918 EXT_CAP_IE(pPkt)->ucLength = 5;
1919
1920 EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */
1921 EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */
1922 EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */
1923 EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */
1924 EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */
1925
1926 /* TDLS_EX_CAP_PEER_UAPSD */
1927 EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28-24));
1928 /* TDLS_EX_CAP_CHAN_SWITCH */
1929 EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30-24));
1930 /* TDLS_EX_CAP_TDLS */
1931 EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37-32));
1932
1933 u4IeLen = IE_SIZE(pPkt);
1934 LR_TDLS_FME_FIELD_FILL(u4IeLen);
1935
1936 /* 3. Frame Formation - (16) Link identifier element */
1937 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
1938 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER;
1939
1940 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
1941 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6);
1942 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6);
1943
1944 u4IeLen = IE_SIZE(pPkt);
1945 LR_TDLS_FME_FIELD_FILL(u4IeLen);
1946
1947 /* 4. Update packet length */
1948 prMsduInfo->len = u4PktLen;
1949 dumpMemory8(ANDROID_LOG_INFO, prMsduInfo->data, u4PktLen);
1950
1951 /* pass to OS */
1952 TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
1953 }
1954
1955
1956 /*----------------------------------------------------------------------------*/
1957 /*! \brief This routine is called to inform firmware to skip channel switch timeout function.
1958 *
1959 * \param[in] prGlueInfo Pointer to the Adapter structure
1960 * \param[in] prInBuf A pointer to the command string buffer
1961 * \param[in] u4InBufLen The length of the buffer
1962 * \param[out] None
1963 *
1964 * \retval None
1965 *
1966 * EX: iwpriv wlan0 set_str_cmd 0_14_[Enable/Disable]
1967
1968 iwpriv wlan0 set_str_cmd 0_14_0
1969 */
1970 /*----------------------------------------------------------------------------*/
1971 static void
1972 TdlsCmdTestScanCtrl(
1973 P_GLUE_INFO_T prGlueInfo,
1974 UINT_8 *prInBuf,
1975 UINT_32 u4InBufLen
1976 )
1977 {
1978 WLAN_STATUS rStatus;
1979 TDLS_CMD_CORE_T rCmd;
1980 UINT_32 u4BufLen;
1981
1982
1983 /* parse arguments */
1984 kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
1985 rCmd.Content.rCmdScanSkip.fgIsEnable = \
1986 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
1987
1988 DBGLOG(TDLS, INFO, ("%s: fgIsEnable = %d\n",
1989 __FUNCTION__, rCmd.Content.rCmdScanSkip.fgIsEnable));
1990
1991 /* command to do this */
1992 rStatus = kalIoctl(prGlueInfo,
1993 TdlsTestScanSkip,
1994 &rCmd,
1995 sizeof(rCmd),
1996 FALSE,
1997 FALSE,
1998 FALSE,
1999 FALSE,
2000 &u4BufLen);
2001
2002 if (rStatus != WLAN_STATUS_SUCCESS)
2003 {
2004 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
2005 return;
2006 }
2007 }
2008
2009
2010 /*----------------------------------------------------------------------------*/
2011 /*! \brief This routine is called to receive a test tear down frame command.
2012 *
2013 * \param[in] prGlueInfo Pointer to the Adapter structure
2014 * \param[in] prInBuf A pointer to the command string buffer
2015 * \param[in] u4InBufLen The length of the buffer
2016 * \param[out] None
2017 *
2018 * \retval None
2019 *
2020 * EX: iwpriv wlan0 set_str_cmd 0_1_3_[IsInitiator]_[ReasonCode]_[Peer MAC]_[Where]
2021
2022 Where 0 (From driver) or 1 (From FW)
2023
2024 iwpriv wlan0 set_str_cmd 0_1_3_1_26_00:11:22:33:44:01_0
2025 */
2026 /*----------------------------------------------------------------------------*/
2027 static void
2028 TdlsCmdTestTearDownRecv(
2029 GLUE_INFO_T *prGlueInfo,
2030 UINT_8 *prInBuf,
2031 UINT_32 u4InBufLen
2032 )
2033 {
2034 ADAPTER_T *prAdapter;
2035 P_BSS_INFO_T prBssInfo;
2036 struct sk_buff *prMsduInfo;
2037 UINT_8 *pPkt;
2038 UINT_32 u4PktLen, u4IeLen;
2039 BOOLEAN fgIsInitiator;
2040 UINT_8 ucReasonCode, aucPeerMac[6];
2041 BOOLEAN fgIsFromWhich;
2042 WLAN_STATUS rStatus;
2043 TDLS_CMD_CORE_T rCmd;
2044 UINT_32 u4BufLen;
2045
2046
2047 /* parse arguments */
2048 fgIsInitiator = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
2049 ucReasonCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
2050 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac);
2051 fgIsFromWhich = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
2052
2053 DBGLOG(TDLS, INFO,
2054 ("<tdls_fme> %s: ReasonCode=%d from "MACSTR" %d\n",
2055 __FUNCTION__, ucReasonCode, MAC2STR(aucPeerMac), fgIsFromWhich));
2056
2057 if (fgIsFromWhich == 0)
2058 {
2059 /* allocate/init packet */
2060 prAdapter = prGlueInfo->prAdapter;
2061 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
2062 u4PktLen = 0;
2063
2064 prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
2065 if (prMsduInfo == NULL) {
2066 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: allocate pkt fail\n", __FUNCTION__));
2067 return;
2068 }
2069
2070 prMsduInfo->dev = prGlueInfo->prDevHandler;
2071 if (prMsduInfo->dev == NULL)
2072 {
2073 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: MsduInfo->dev == NULL\n", __FUNCTION__));
2074 kalPacketFree(prGlueInfo, prMsduInfo);
2075 return;
2076 }
2077
2078 /* make up frame content */
2079 /* 1. 802.3 header */
2080 kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
2081 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
2082 kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN);
2083 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
2084 *(UINT_16 *)pPkt = htons(TDLS_FRM_PROT_TYPE);
2085 LR_TDLS_FME_FIELD_FILL(2);
2086
2087 /* 2. payload type */
2088 *pPkt = TDLS_FRM_PAYLOAD_TYPE;
2089 LR_TDLS_FME_FIELD_FILL(1);
2090
2091 /* 3. Frame Formation - (1) Category */
2092 *pPkt = TDLS_FRM_CATEGORY;
2093 LR_TDLS_FME_FIELD_FILL(1);
2094
2095 /* 3. Frame Formation - (2) Action */
2096 *pPkt = TDLS_FRM_ACTION_TEARDOWN;
2097 LR_TDLS_FME_FIELD_FILL(1);
2098
2099 /* 3. Frame Formation - (3) Reason Code */
2100 *pPkt = ucReasonCode;
2101 *(pPkt+1) = 0x00;
2102 LR_TDLS_FME_FIELD_FILL(2);
2103
2104 /* 3. Frame Formation - (16) Link identifier element */
2105 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
2106 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER;
2107
2108 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
2109 if (fgIsInitiator == 1)
2110 {
2111 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6);
2112 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6);
2113 }
2114 else
2115 {
2116 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6);
2117 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6);
2118 }
2119
2120 u4IeLen = IE_SIZE(pPkt);
2121 LR_TDLS_FME_FIELD_FILL(u4IeLen);
2122
2123 /* 4. Update packet length */
2124 prMsduInfo->len = u4PktLen;
2125 dumpMemory8(ANDROID_LOG_INFO, prMsduInfo->data, u4PktLen);
2126
2127 /* pass to OS */
2128 TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
2129 }
2130 else
2131 {
2132 kalMemZero(&rCmd, sizeof(rCmd));
2133 kalMemCopy(rCmd.aucPeerMac, aucPeerMac, 6);
2134 rCmd.Content.rCmdTearDownRcv.u4ReasonCode = (UINT32)ucReasonCode;
2135
2136 /* command to do this */
2137 rStatus = kalIoctl(prGlueInfo,
2138 TdlsTestTearDownRecv,
2139 &rCmd,
2140 sizeof(rCmd),
2141 FALSE,
2142 FALSE,
2143 FALSE,
2144 FALSE,
2145 &u4BufLen);
2146
2147 if (rStatus != WLAN_STATUS_SUCCESS)
2148 {
2149 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
2150 return;
2151 }
2152 }
2153 }
2154
2155
2156 /*----------------------------------------------------------------------------*/
2157 /*! \brief This routine is called to inform firmware to skip tx fail case.
2158 *
2159 * \param[in] prGlueInfo Pointer to the Adapter structure
2160 * \param[in] prInBuf A pointer to the command string buffer
2161 * \param[in] u4InBufLen The length of the buffer
2162 * \param[out] None
2163 *
2164 * \retval None
2165 *
2166 * EX: iwpriv wlan0 set_str_cmd 0_7_[Enable/Disable]
2167
2168 iwpriv wlan0 set_str_cmd 0_7_1
2169 */
2170 /*----------------------------------------------------------------------------*/
2171 static void
2172 TdlsCmdTestTxFailSkip(
2173 P_GLUE_INFO_T prGlueInfo,
2174 UINT_8 *prInBuf,
2175 UINT_32 u4InBufLen
2176 )
2177 {
2178 WLAN_STATUS rStatus;
2179 TDLS_CMD_CORE_T rCmd;
2180 UINT_32 u4BufLen;
2181
2182
2183 /* parse arguments */
2184 kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
2185 rCmd.Content.rCmdTxFailSkip.fgIsEnable = \
2186 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
2187
2188 DBGLOG(TDLS, INFO, ("%s: fgIsEnable = %d\n",
2189 __FUNCTION__, rCmd.Content.rCmdTxFailSkip.fgIsEnable));
2190
2191 /* command to do this */
2192 rStatus = kalIoctl(prGlueInfo,
2193 TdlsTestTxFailSkip,
2194 &rCmd,
2195 sizeof(rCmd),
2196 FALSE,
2197 FALSE,
2198 FALSE,
2199 FALSE,
2200 &u4BufLen);
2201
2202 if (rStatus != WLAN_STATUS_SUCCESS)
2203 {
2204 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
2205 return;
2206 }
2207 }
2208
2209
2210 /*----------------------------------------------------------------------------*/
2211 /*! \brief This routine is called to send a test frame command to wifi task.
2212 *
2213 * \param[in] prGlueInfo Pointer to the Adapter structure
2214 * \param[in] prInBuf A pointer to the command string buffer
2215 * \param[in] u4InBufLen The length of the buffer
2216 * \param[out] None
2217 *
2218 * \retval None
2219 *
2220 * EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC]
2221
2222 iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01
2223 *
2224 * EX: iwpriv wlan0 set_str_cmd 0_12_2_[FrameType]_[DialogToken]_[Peer MAC]
2225
2226 iwpriv wlan0 set_str_cmd 0_12_2_0_1_00:11:22:33:44:01
2227 */
2228 /*----------------------------------------------------------------------------*/
2229 static void
2230 TdlsCmdTestTxTdlsFrame(
2231 P_GLUE_INFO_T prGlueInfo,
2232 UINT_8 *prInBuf,
2233 UINT_32 u4InBufLen
2234 )
2235 {
2236 PARAM_CUSTOM_TDLS_CMD_STRUC_T rCmd;
2237 UINT32 u4Subcmd;
2238 UINT_32 u4BufLen;
2239
2240
2241 /* parse sub-command */
2242 u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
2243 DBGLOG(TDLS, INFO, ("<tdls_cmd> test tx tdls frame sub command = %u\n",
2244 u4Subcmd));
2245
2246 /* parse command arguments */
2247 rCmd.ucFmeType = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen);
2248
2249 switch(u4Subcmd)
2250 {
2251 case TDLS_FRM_ACTION_SETUP_REQ:
2252 case TDLS_FRM_ACTION_SETUP_RSP:
2253 case TDLS_FRM_ACTION_CONFIRM:
2254 rCmd.ucToken = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen);
2255 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr);
2256
2257 DBGLOG(TDLS, INFO, ("<tdls_cmd> setup FmeType=%d Token=%d to "
2258 "["MACSTR"]\n",
2259 rCmd.ucFmeType, rCmd.ucToken,
2260 MAC2STR(rCmd.arRspAddr)));
2261 break;
2262
2263 default:
2264 DBGLOG(TDLS, ERROR, ("<tdls_cmd> wrong test tx frame sub command\n"));
2265 return;
2266 }
2267
2268 /* send command to wifi task to handle */
2269 kalIoctl(prGlueInfo,
2270 TdlsTestTdlsFrameSend,
2271 (PVOID)&rCmd,
2272 sizeof(PARAM_CUSTOM_TDLS_CMD_STRUC_T),
2273 FALSE,
2274 FALSE,
2275 TRUE,
2276 FALSE,
2277 &u4BufLen);
2278 }
2279
2280
2281 /*----------------------------------------------------------------------------*/
2282 /*! \brief This routine is called to send a test frame command to wifi task.
2283 *
2284 * \param[in] prGlueInfo Pointer to the Adapter structure
2285 * \param[in] prInBuf A pointer to the command string buffer
2286 * \param[in] u4InBufLen The length of the buffer
2287 * \param[out] None
2288 *
2289 * \retval None
2290 *
2291 * EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_
2292 [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_
2293 [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_
2294 [Timeout]_[Peer MAC]
2295
2296 iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01
2297 */
2298 /*----------------------------------------------------------------------------*/
2299 static void
2300 TdlsCmdTestTxFrame(
2301 P_GLUE_INFO_T prGlueInfo,
2302 UINT_8 *prInBuf,
2303 UINT_32 u4InBufLen
2304 )
2305 {
2306 PARAM_CUSTOM_TDLS_CMD_STRUC_T rCmd;
2307 TDLS_STATUS u4Status;
2308 UINT_32 u4Subcmd;
2309 UINT_32 u4BufLen;
2310
2311
2312 /* parse sub-command */
2313 u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
2314 DBGLOG(TDLS, INFO, ("<tdls_cmd> test tx frame sub command = %u\n",
2315 (UINT32)u4Subcmd));
2316
2317 /* parse command arguments */
2318 switch(u4Subcmd)
2319 {
2320 case TDLS_FRM_ACTION_SETUP_REQ:
2321 u4Status = TdlsCmdTestTxFmeSetupReqBufTranslate(
2322 prInBuf, u4InBufLen, &rCmd);
2323 break;
2324
2325 default:
2326 DBGLOG(TDLS, ERROR, ("<tdls_cmd> wrong test tx frame sub command\n"));
2327 return;
2328 }
2329
2330 if (u4Status != TDLS_STATUS_SUCCESS)
2331 {
2332 DBGLOG(TDLS, ERROR, ("<tdls_cmd> command parse fail\n"));
2333 return;
2334 }
2335
2336 /* send command to wifi task to handle */
2337 kalIoctl(prGlueInfo,
2338 TdlsTestFrameSend,
2339 (PVOID)&rCmd,
2340 sizeof(PARAM_CUSTOM_TDLS_CMD_STRUC_T),
2341 FALSE,
2342 FALSE,
2343 TRUE,
2344 FALSE,
2345 &u4BufLen);
2346 }
2347
2348
2349 /*----------------------------------------------------------------------------*/
2350 /*!
2351 * @brief Parse the TDLS test frame command, setup request
2352 *
2353 * @param CmdBuf Pointer to the buffer.
2354 * @param BufLen Record buffer length.
2355 * @param CmdTspec Pointer to the structure.
2356 *
2357 * @retval WLAN_STATUS_SUCCESS: Translate OK.
2358 * @retval WLAN_STATUS_FAILURE: Translate fail.
2359 * @usage iwpriv wlan0 set_str_cmd [tdls]_[command]
2360 *
2361 * EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_
2362 [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_
2363 [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_
2364 [Timeout]_[Peer MAC]
2365
2366 iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01
2367 */
2368 /*----------------------------------------------------------------------------*/
2369 static TDLS_STATUS
2370 TdlsCmdTestTxFmeSetupReqBufTranslate(
2371 UINT_8 *pCmdBuf,
2372 UINT_32 u4BufLen,
2373 PARAM_CUSTOM_TDLS_CMD_STRUC_T *prCmd
2374 )
2375 {
2376 // dumpMemory8(ANDROID_LOG_INFO, pCmdBuf, u4BufLen);
2377
2378 prCmd->ucFmeType = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2379 prCmd->ucToken = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2380 prCmd->u2Cap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2381 prCmd->ucExCap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2382 prCmd->arSupRate[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2383 prCmd->arSupRate[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2384 prCmd->arSupRate[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2385 prCmd->arSupRate[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2386 prCmd->arSupChan[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2387 prCmd->arSupChan[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2388 prCmd->arSupChan[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2389 prCmd->arSupChan[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2390 prCmd->u4Timeout = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen);
2391 CmdStringMacParse(pCmdBuf, &pCmdBuf, &u4BufLen, prCmd->arRspAddr);
2392
2393 DBGLOG(TDLS, INFO, ("<tdls_cmd> command content =\n"));
2394 DBGLOG(TDLS, INFO, ("\tPeer MAC = "MACSTR"\n", MAC2STR(prCmd->arRspAddr)));
2395 DBGLOG(TDLS, INFO, ("\tToken = %u, Cap = 0x%x, ExCap = 0x%x, Timeout = %us "
2396 "FrameType = %u\n",
2397 (UINT32)prCmd->ucToken, prCmd->u2Cap, prCmd->ucExCap,
2398 (UINT32)prCmd->u4Timeout, (UINT32)prCmd->ucFmeType));
2399 DBGLOG(TDLS, INFO, ("\tSupRate = 0x%x %x %x %x\n",
2400 prCmd->arSupRate[0], prCmd->arSupRate[1],
2401 prCmd->arSupRate[2], prCmd->arSupRate[3]));
2402 DBGLOG(TDLS, INFO, ("\tSupChan = %d %d %d %d\n",
2403 prCmd->arSupChan[0], prCmd->arSupChan[1],
2404 prCmd->arSupChan[2], prCmd->arSupChan[3]));
2405
2406 return TDLS_STATUS_SUCCESS;
2407 }
2408
2409
2410 /*----------------------------------------------------------------------------*/
2411 /*! \brief This routine is called to update a TDLS peer.
2412 *
2413 * \param[in] prGlueInfo Pointer to the Adapter structure
2414 * \param[in] prInBuf A pointer to the command string buffer
2415 * \param[in] u4InBufLen The length of the buffer
2416 * \param[out] None
2417 *
2418 * \retval None
2419 *
2420 * EX: iwpriv wlan0 set_str_cmd 0_3_[Responder MAC]
2421
2422 iwpriv wlan0 set_str_cmd 0_3_00:11:22:33:44:01
2423 */
2424 /*----------------------------------------------------------------------------*/
2425 static void
2426 TdlsCmdTestUpdatePeer(
2427 P_GLUE_INFO_T prGlueInfo,
2428 UINT_8 *prInBuf,
2429 UINT_32 u4InBufLen
2430 )
2431 {
2432 PARAM_CUSTOM_TDLS_CMD_STRUC_T rCmd;
2433 struct wireless_dev *prWdev;
2434
2435
2436 /* reset */
2437 kalMemZero(&rCmd, sizeof(rCmd));
2438
2439 /* parse arguments */
2440 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr);
2441
2442 /* init */
2443 rCmd.rPeerInfo.supported_rates = rCmd.arSupRate;
2444 rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa;
2445 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2446 rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa;
2447 #endif
2448 rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER);
2449 rCmd.rPeerInfo.uapsd_queues = 0xf; /* all AC */
2450 rCmd.rPeerInfo.max_sp = 0; /* delivery all packets */
2451
2452 /* send command to wifi task to handle */
2453 prWdev = prGlueInfo->prDevHandler->ieee80211_ptr;
2454 mtk_cfg80211_add_station(\
2455 prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo);
2456
2457 /* update */
2458 TdlsexCfg80211TdlsOper(\
2459 prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, NL80211_TDLS_ENABLE_LINK);
2460 }
2461
2462
2463 /*----------------------------------------------------------------------------*/
2464 /*! \brief This routine is called to receive a Null frame from the peer.
2465 *
2466 * \param[in] prAdapter Pointer to the Adapter structure
2467 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
2468 * \param[in] u4SetBufferLen The length of the set buffer
2469 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
2470 * bytes read from the set buffer. If the call failed due to invalid length of
2471 * the set buffer, returns the amount of storage needed.
2472 *
2473 * \retval TDLS_STATUS_xx
2474 *
2475 * EX: iwpriv wlan0 set_str_cmd 0_5_[Responder MAC]_[PM bit]
2476
2477 iwpriv wlan0 set_str_cmd 0_5_00:11:22:33:44:01_1
2478 */
2479 /*----------------------------------------------------------------------------*/
2480 static void
2481 TdlsCmdTestNullRecv(
2482 P_GLUE_INFO_T prGlueInfo,
2483 UINT_8 *prInBuf,
2484 UINT_32 u4InBufLen
2485 )
2486 {
2487 WLAN_STATUS rStatus;
2488 TDLS_CMD_CORE_T rCmd;
2489 UINT_32 u4BufLen;
2490
2491
2492 /* parse arguments */
2493 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
2494 rCmd.Content.rCmdNullRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
2495
2496 DBGLOG(TDLS, INFO, ("%s: ["MACSTR"] u4PM = %u\n",
2497 __FUNCTION__, MAC2STR(rCmd.aucPeerMac),
2498 (UINT32)rCmd.Content.rCmdNullRcv.u4PM));
2499
2500 /* command to do this */
2501 rStatus = kalIoctl(prGlueInfo,
2502 TdlsTestNullRecv,
2503 &rCmd,
2504 sizeof(rCmd),
2505 FALSE,
2506 FALSE,
2507 FALSE,
2508 FALSE,
2509 &u4BufLen);
2510
2511 if (rStatus != WLAN_STATUS_SUCCESS)
2512 {
2513 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
2514 return;
2515 }
2516 }
2517
2518
2519 /*----------------------------------------------------------------------------*/
2520 /*! \brief This routine is called to send a data frame to the peer periodically.
2521 *
2522 * \param[in] prAdapter Pointer to the Adapter structure
2523 * \param[in] u4Param no use
2524 * \param[out] None
2525 *
2526 * \retval None
2527 *
2528 * EX: iwpriv wlan0 set_str_cmd 0_15_[Responder MAC]_[Interval: ms]_[Enable/Disable]
2529
2530 iwpriv wlan0 set_str_cmd 0_15_00:11:22:33:44:01_5000_1
2531 */
2532 /*----------------------------------------------------------------------------*/
2533 static VOID
2534 TdlsTimerTestDataContSend(
2535 ADAPTER_T *prAdapter,
2536 UINT_32 u4Param
2537 )
2538 {
2539 GLUE_INFO_T *prGlueInfo;
2540 struct sk_buff *prMsduInfo;
2541 UINT_8 *prPkt;
2542
2543
2544 /* init */
2545 prGlueInfo = prAdapter->prGlueInfo;
2546
2547 /* allocate a data frame */
2548 prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt);
2549 if (prMsduInfo == NULL)
2550 {
2551 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s allocate pkt fail!\n",
2552 __FUNCTION__));
2553 return;
2554 }
2555
2556 /* init dev */
2557 prMsduInfo->dev = prGlueInfo->prDevHandler;
2558 if (prMsduInfo->dev == NULL)
2559 {
2560 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s prMsduInfo->dev == NULL!\n",
2561 __FUNCTION__));
2562 kalPacketFree(prGlueInfo, prMsduInfo);
2563 return;
2564 }
2565
2566 /* init packet */
2567 prMsduInfo->len = 1000;
2568 kalMemCopy(prMsduInfo->data, aucTdlsTestDataSPeerMac, 6);
2569 kalMemCopy(prMsduInfo->data+6, prAdapter->rMyMacAddr, 6);
2570 *(UINT_16 *)(prMsduInfo->data+12) = 0x0800;
2571
2572 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s try to send a data frame to "MACSTR"\n",
2573 __FUNCTION__, MAC2STR(aucTdlsTestDataSPeerMac)));
2574
2575 /* simulate OS to send the packet */
2576 wlanHardStartXmit(prMsduInfo, prMsduInfo->dev);
2577
2578 /* restart test timer */
2579 cnmTimerStartTimer(prAdapter,
2580 &rTdlsTimerTestDataSend,
2581 u2TdlsTestDataSInterval);
2582 }
2583
2584
2585 /*----------------------------------------------------------------------------*/
2586 /*! \brief This routine is called to receive a Channel Switch Request frame.
2587 *
2588 * \param[in] prAdapter Pointer to the Adapter structure
2589 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
2590 * \param[in] u4SetBufferLen The length of the set buffer
2591 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
2592 * bytes read from the set buffer. If the call failed due to invalid length of
2593 * the set buffer, returns the amount of storage needed.
2594 *
2595 * \retval TDLS_STATUS_xx
2596 *
2597 */
2598 /*----------------------------------------------------------------------------*/
2599 static TDLS_STATUS
2600 TdlsTestChStReqRecv(
2601 ADAPTER_T *prAdapter,
2602 VOID *pvSetBuffer,
2603 UINT_32 u4SetBufferLen,
2604 UINT_32 *pu4SetInfoLen
2605 )
2606 {
2607 TDLS_CMD_CORE_T *prCmdContent;
2608 WLAN_STATUS rStatus;
2609
2610
2611 /* init command buffer */
2612 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
2613 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_REQ;
2614
2615 /* send the command */
2616 rStatus = wlanSendSetQueryCmd (
2617 prAdapter, /* prAdapter */
2618 CMD_ID_TDLS_CORE, /* ucCID */
2619 TRUE, /* fgSetQuery */
2620 FALSE, /* fgNeedResp */
2621 FALSE, /* fgIsOid */
2622 NULL,
2623 NULL, /* pfCmdTimeoutHandler */
2624 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
2625 (PUINT_8) prCmdContent, /* pucInfoBuffer */
2626 NULL, /* pvSetQueryBuffer */
2627 0 /* u4SetQueryBufferLen */
2628 );
2629
2630 if (rStatus != WLAN_STATUS_PENDING)
2631 {
2632 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
2633 __FUNCTION__));
2634 return TDLS_STATUS_RESOURCES;
2635 }
2636
2637 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
2638 return TDLS_STATUS_SUCCESS;
2639 }
2640
2641
2642 /*----------------------------------------------------------------------------*/
2643 /*! \brief This routine is called to receive a Channel Switch Response frame.
2644 *
2645 * \param[in] prAdapter Pointer to the Adapter structure
2646 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
2647 * \param[in] u4SetBufferLen The length of the set buffer
2648 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
2649 * bytes read from the set buffer. If the call failed due to invalid length of
2650 * the set buffer, returns the amount of storage needed.
2651 *
2652 * \retval TDLS_STATUS_xx
2653 *
2654 */
2655 /*----------------------------------------------------------------------------*/
2656 static TDLS_STATUS
2657 TdlsTestChStRspRecv(
2658 ADAPTER_T *prAdapter,
2659 VOID *pvSetBuffer,
2660 UINT_32 u4SetBufferLen,
2661 UINT_32 *pu4SetInfoLen
2662 )
2663 {
2664 TDLS_CMD_CORE_T *prCmdContent;
2665 WLAN_STATUS rStatus;
2666
2667
2668 /* init command buffer */
2669 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
2670 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_RSP;
2671
2672 /* send the command */
2673 rStatus = wlanSendSetQueryCmd (
2674 prAdapter, /* prAdapter */
2675 CMD_ID_TDLS_CORE, /* ucCID */
2676 TRUE, /* fgSetQuery */
2677 FALSE, /* fgNeedResp */
2678 FALSE, /* fgIsOid */
2679 NULL,
2680 NULL, /* pfCmdTimeoutHandler */
2681 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
2682 (PUINT_8) prCmdContent, /* pucInfoBuffer */
2683 NULL, /* pvSetQueryBuffer */
2684 0 /* u4SetQueryBufferLen */
2685 );
2686
2687 if (rStatus != WLAN_STATUS_PENDING)
2688 {
2689 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
2690 __FUNCTION__));
2691 return TDLS_STATUS_RESOURCES;
2692 }
2693
2694 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
2695 return TDLS_STATUS_SUCCESS;
2696 }
2697
2698
2699 /*----------------------------------------------------------------------------*/
2700 /*!
2701 * \brief This routine is called to send a test frame.
2702 *
2703 * \param[in] prAdapter Pointer to the Adapter structure
2704 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
2705 * \param[in] u4SetBufferLen The length of the set buffer
2706 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
2707 * bytes read from the set buffer. If the call failed due to invalid length of
2708 * the set buffer, returns the amount of storage needed.
2709 *
2710 * \retval TDLS_STATUS_xx
2711 *
2712 */
2713 /*----------------------------------------------------------------------------*/
2714 static TDLS_STATUS
2715 TdlsTestFrameSend(
2716 ADAPTER_T *prAdapter,
2717 VOID *pvSetBuffer,
2718 UINT_32 u4SetBufferLen,
2719 UINT_32 *pu4SetInfoLen
2720 )
2721 {
2722 GLUE_INFO_T *prGlueInfo;
2723 PARAM_CUSTOM_TDLS_CMD_STRUC_T *prCmd;
2724 P_BSS_INFO_T prBssInfo;
2725 struct sk_buff *prMsduInfo;
2726 UINT_8 *pPkt;
2727 UINT_32 u4PktLen, u4IeLen;
2728
2729
2730 /* sanity check */
2731 ASSERT(prAdapter);
2732 ASSERT(pvSetBuffer);
2733 ASSERT(pu4SetInfoLen);
2734
2735 DBGLOG(TDLS, INFO, ("<tdls_fme> %s\n", __FUNCTION__));
2736
2737 if(u4SetBufferLen == 0)
2738 return TDLS_STATUS_INVALID_LENGTH;
2739
2740 /* allocate/init packet */
2741 prGlueInfo = (GLUE_INFO_T *)prAdapter->prGlueInfo;
2742 prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUC_T *)pvSetBuffer;
2743 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
2744 *pu4SetInfoLen = u4SetBufferLen;
2745 u4PktLen = 0;
2746
2747 prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
2748 if (prMsduInfo == NULL) {
2749 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: allocate pkt fail\n", __FUNCTION__));
2750 return TDLS_STATUS_RESOURCES;
2751 }
2752
2753 prMsduInfo->dev = prGlueInfo->prDevHandler;
2754 if (prMsduInfo->dev == NULL)
2755 {
2756 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: MsduInfo->dev == NULL\n", __FUNCTION__));
2757 kalPacketFree(prGlueInfo, prMsduInfo);
2758 return TDLS_STATUS_FAILURE;
2759 }
2760
2761 /* make up frame content */
2762 /* 1. 802.3 header */
2763 kalMemCopy(pPkt, prCmd->arRspAddr, TDLS_FME_MAC_ADDR_LEN);
2764 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
2765 kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
2766 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
2767 *(UINT_16 *)pPkt = htons(TDLS_FRM_PROT_TYPE);
2768 LR_TDLS_FME_FIELD_FILL(2);
2769
2770 /* 2. payload type */
2771 *pPkt = TDLS_FRM_PAYLOAD_TYPE;
2772 LR_TDLS_FME_FIELD_FILL(1);
2773
2774 /* 3. Frame Formation - (1) Category */
2775 *pPkt = TDLS_FRM_CATEGORY;
2776 LR_TDLS_FME_FIELD_FILL(1);
2777
2778 /* 3. Frame Formation - (2) Action */
2779 *pPkt = prCmd->ucFmeType;
2780 LR_TDLS_FME_FIELD_FILL(1);
2781
2782 /* 3. Frame Formation - (3) Dialog token */
2783 *pPkt = prCmd->ucToken;
2784 LR_TDLS_FME_FIELD_FILL(1);
2785
2786 /* 3. Frame Formation - (4) Capability */
2787 WLAN_SET_FIELD_16(pPkt, prCmd->u2Cap);
2788 LR_TDLS_FME_FIELD_FILL(2);
2789
2790 /* 4. Append general IEs */
2791 u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt);
2792 LR_TDLS_FME_FIELD_FILL(u4IeLen);
2793
2794 /* 3. Frame Formation - (10) Extended capabilities element */
2795 EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP;
2796 EXT_CAP_IE(pPkt)->ucLength = 5;
2797
2798 EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */
2799 EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */
2800 EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */
2801 EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */
2802 EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */
2803
2804 if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD)
2805 EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28-24));
2806 if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH)
2807 EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30-24));
2808 if (prCmd->ucExCap & TDLS_EX_CAP_TDLS)
2809 EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37-32));
2810
2811 u4IeLen = IE_SIZE(pPkt);
2812 LR_TDLS_FME_FIELD_FILL(u4IeLen);
2813
2814 /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */
2815 TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL;
2816 TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5;
2817
2818 TIMEOUT_INTERVAL_IE(pPkt)->ucType = IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME;
2819 TIMEOUT_INTERVAL_IE(pPkt)->u4Value = htonl(prCmd->u4Timeout);
2820
2821 u4IeLen = IE_SIZE(pPkt);
2822 LR_TDLS_FME_FIELD_FILL(u4IeLen);
2823
2824 /* 3. Frame Formation - (16) Link identifier element */
2825 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER;
2826 TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER;
2827
2828 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6);
2829 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6);
2830 kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prCmd->arRspAddr, 6);
2831
2832 u4IeLen = IE_SIZE(pPkt);
2833 LR_TDLS_FME_FIELD_FILL(u4IeLen);
2834
2835 /* 4. Update packet length */
2836 prMsduInfo->len = u4PktLen;
2837 dumpMemory8(ANDROID_LOG_INFO, prMsduInfo->data, u4PktLen);
2838
2839 /* 5. send the data frame */
2840 wlanHardStartXmit(prMsduInfo, prMsduInfo->dev);
2841 return TDLS_STATUS_SUCCESS;
2842 }
2843
2844
2845 /*----------------------------------------------------------------------------*/
2846 /*! \brief This routine is called to receive a NULL frame.
2847 *
2848 * \param[in] prAdapter Pointer to the Adapter structure
2849 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
2850 * \param[in] u4SetBufferLen The length of the set buffer
2851 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
2852 * bytes read from the set buffer. If the call failed due to invalid length of
2853 * the set buffer, returns the amount of storage needed.
2854 *
2855 * \retval TDLS_STATUS_xx
2856 *
2857 */
2858 /*----------------------------------------------------------------------------*/
2859 static TDLS_STATUS
2860 TdlsTestNullRecv(
2861 ADAPTER_T *prAdapter,
2862 VOID *pvSetBuffer,
2863 UINT_32 u4SetBufferLen,
2864 UINT_32 *pu4SetInfoLen
2865 )
2866 {
2867 TDLS_CMD_CORE_T *prCmdContent;
2868 WLAN_STATUS rStatus;
2869
2870
2871 /* init command buffer */
2872 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
2873 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_NULL_RCV;
2874
2875 /* send the command */
2876 rStatus = wlanSendSetQueryCmd (
2877 prAdapter, /* prAdapter */
2878 CMD_ID_TDLS_CORE, /* ucCID */
2879 TRUE, /* fgSetQuery */
2880 FALSE, /* fgNeedResp */
2881 FALSE, /* fgIsOid */
2882 NULL,
2883 NULL, /* pfCmdTimeoutHandler */
2884 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
2885 (PUINT_8) prCmdContent, /* pucInfoBuffer */
2886 NULL, /* pvSetQueryBuffer */
2887 0 /* u4SetQueryBufferLen */
2888 );
2889
2890 if (rStatus != WLAN_STATUS_PENDING)
2891 {
2892 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
2893 __FUNCTION__));
2894 return TDLS_STATUS_RESOURCES;
2895 }
2896
2897 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
2898 return TDLS_STATUS_SUCCESS;
2899 }
2900
2901
2902 /*----------------------------------------------------------------------------*/
2903 /*! \brief This routine is called to receive a PTI frame.
2904 *
2905 * \param[in] prAdapter Pointer to the Adapter structure
2906 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
2907 * \param[in] u4SetBufferLen The length of the set buffer
2908 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
2909 * bytes read from the set buffer. If the call failed due to invalid length of
2910 * the set buffer, returns the amount of storage needed.
2911 *
2912 * \retval TDLS_STATUS_xx
2913 *
2914 */
2915 /*----------------------------------------------------------------------------*/
2916 static TDLS_STATUS
2917 TdlsTestPtiReqRecv(
2918 ADAPTER_T *prAdapter,
2919 VOID *pvSetBuffer,
2920 UINT_32 u4SetBufferLen,
2921 UINT_32 *pu4SetInfoLen
2922 )
2923 {
2924 TDLS_CMD_CORE_T *prCmdContent;
2925 WLAN_STATUS rStatus;
2926
2927
2928 /* init command buffer */
2929 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
2930 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_REQ;
2931
2932 /* send the command */
2933 rStatus = wlanSendSetQueryCmd (
2934 prAdapter, /* prAdapter */
2935 CMD_ID_TDLS_CORE, /* ucCID */
2936 TRUE, /* fgSetQuery */
2937 FALSE, /* fgNeedResp */
2938 FALSE, /* fgIsOid */
2939 NULL,
2940 NULL, /* pfCmdTimeoutHandler */
2941 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
2942 (PUINT_8) prCmdContent, /* pucInfoBuffer */
2943 NULL, /* pvSetQueryBuffer */
2944 0 /* u4SetQueryBufferLen */
2945 );
2946
2947 if (rStatus != WLAN_STATUS_PENDING)
2948 {
2949 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
2950 __FUNCTION__));
2951 return TDLS_STATUS_RESOURCES;
2952 }
2953
2954 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
2955 return TDLS_STATUS_SUCCESS;
2956 }
2957
2958
2959 /*----------------------------------------------------------------------------*/
2960 /*! \brief This routine is called to receive a PTI response frame.
2961 *
2962 * \param[in] prAdapter Pointer to the Adapter structure
2963 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
2964 * \param[in] u4SetBufferLen The length of the set buffer
2965 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
2966 * bytes read from the set buffer. If the call failed due to invalid length of
2967 * the set buffer, returns the amount of storage needed.
2968 *
2969 * \retval TDLS_STATUS_xx
2970 *
2971 */
2972 /*----------------------------------------------------------------------------*/
2973 static TDLS_STATUS
2974 TdlsTestPtiRspRecv(
2975 ADAPTER_T *prAdapter,
2976 VOID *pvSetBuffer,
2977 UINT_32 u4SetBufferLen,
2978 UINT_32 *pu4SetInfoLen
2979 )
2980 {
2981 TDLS_CMD_CORE_T *prCmdContent;
2982 WLAN_STATUS rStatus;
2983
2984
2985 /* init command buffer */
2986 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
2987 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_RSP;
2988
2989 /* send the command */
2990 rStatus = wlanSendSetQueryCmd (
2991 prAdapter, /* prAdapter */
2992 CMD_ID_TDLS_CORE, /* ucCID */
2993 TRUE, /* fgSetQuery */
2994 FALSE, /* fgNeedResp */
2995 FALSE, /* fgIsOid */
2996 NULL,
2997 NULL, /* pfCmdTimeoutHandler */
2998 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
2999 (PUINT_8) prCmdContent, /* pucInfoBuffer */
3000 NULL, /* pvSetQueryBuffer */
3001 0 /* u4SetQueryBufferLen */
3002 );
3003
3004 if (rStatus != WLAN_STATUS_PENDING)
3005 {
3006 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
3007 __FUNCTION__));
3008 return TDLS_STATUS_RESOURCES;
3009 }
3010
3011 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
3012 return TDLS_STATUS_SUCCESS;
3013 }
3014
3015
3016 /*----------------------------------------------------------------------------*/
3017 /*! \brief This routine is called to receive a Tear Down frame.
3018 *
3019 * \param[in] prAdapter Pointer to the Adapter structure
3020 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
3021 * \param[in] u4SetBufferLen The length of the set buffer
3022 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
3023 * bytes read from the set buffer. If the call failed due to invalid length of
3024 * the set buffer, returns the amount of storage needed.
3025 *
3026 * \retval TDLS_STATUS_xx
3027 *
3028 */
3029 /*----------------------------------------------------------------------------*/
3030 static TDLS_STATUS
3031 TdlsTestTearDownRecv(
3032 ADAPTER_T *prAdapter,
3033 VOID *pvSetBuffer,
3034 UINT_32 u4SetBufferLen,
3035 UINT_32 *pu4SetInfoLen
3036 )
3037 {
3038 TDLS_CMD_CORE_T *prCmdContent;
3039 WLAN_STATUS rStatus;
3040
3041
3042 /* init command buffer */
3043 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
3044 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TEAR_DOWN;
3045
3046 /* send the command */
3047 rStatus = wlanSendSetQueryCmd (
3048 prAdapter, /* prAdapter */
3049 CMD_ID_TDLS_CORE, /* ucCID */
3050 TRUE, /* fgSetQuery */
3051 FALSE, /* fgNeedResp */
3052 FALSE, /* fgIsOid */
3053 NULL,
3054 NULL, /* pfCmdTimeoutHandler */
3055 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
3056 (PUINT_8) prCmdContent, /* pucInfoBuffer */
3057 NULL, /* pvSetQueryBuffer */
3058 0 /* u4SetQueryBufferLen */
3059 );
3060
3061 if (rStatus != WLAN_STATUS_PENDING)
3062 {
3063 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
3064 __FUNCTION__));
3065 return TDLS_STATUS_RESOURCES;
3066 }
3067
3068 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
3069 return TDLS_STATUS_SUCCESS;
3070 }
3071
3072
3073 /*----------------------------------------------------------------------------*/
3074 /*! \brief This routine is called to receive a data frame.
3075 *
3076 * \param[in] prAdapter Pointer to the Adapter structure
3077 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
3078 * \param[in] u4SetBufferLen The length of the set buffer
3079 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
3080 * bytes read from the set buffer. If the call failed due to invalid length of
3081 * the set buffer, returns the amount of storage needed.
3082 *
3083 * \retval TDLS_STATUS_xx
3084 *
3085 */
3086 /*----------------------------------------------------------------------------*/
3087 static TDLS_STATUS
3088 TdlsTestDataRecv(
3089 ADAPTER_T *prAdapter,
3090 VOID *pvSetBuffer,
3091 UINT_32 u4SetBufferLen,
3092 UINT_32 *pu4SetInfoLen
3093 )
3094 {
3095 TDLS_CMD_CORE_T *prCmdContent;
3096 WLAN_STATUS rStatus;
3097
3098
3099 /* init command buffer */
3100 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
3101 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_DATA_RCV;
3102
3103 /* send the command */
3104 rStatus = wlanSendSetQueryCmd (
3105 prAdapter, /* prAdapter */
3106 CMD_ID_TDLS_CORE, /* ucCID */
3107 TRUE, /* fgSetQuery */
3108 FALSE, /* fgNeedResp */
3109 FALSE, /* fgIsOid */
3110 NULL,
3111 NULL, /* pfCmdTimeoutHandler */
3112 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
3113 (PUINT_8) prCmdContent, /* pucInfoBuffer */
3114 NULL, /* pvSetQueryBuffer */
3115 0 /* u4SetQueryBufferLen */
3116 );
3117
3118 if (rStatus != WLAN_STATUS_PENDING)
3119 {
3120 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
3121 __FUNCTION__));
3122 return TDLS_STATUS_RESOURCES;
3123 }
3124
3125 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
3126 return TDLS_STATUS_SUCCESS;
3127 }
3128
3129
3130 /*----------------------------------------------------------------------------*/
3131 /*! \brief This routine is called to skip PTI tx fail status.
3132 *
3133 * \param[in] prAdapter Pointer to the Adapter structure
3134 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
3135 * \param[in] u4SetBufferLen The length of the set buffer
3136 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
3137 * bytes read from the set buffer. If the call failed due to invalid length of
3138 * the set buffer, returns the amount of storage needed.
3139 *
3140 * \retval TDLS_STATUS_xx
3141 *
3142 */
3143 /*----------------------------------------------------------------------------*/
3144 static TDLS_STATUS
3145 TdlsTestPtiTxFail(
3146 ADAPTER_T *prAdapter,
3147 VOID *pvSetBuffer,
3148 UINT_32 u4SetBufferLen,
3149 UINT_32 *pu4SetInfoLen
3150 )
3151 {
3152 TDLS_CMD_CORE_T *prCmdContent;
3153 WLAN_STATUS rStatus;
3154
3155
3156 /* init command buffer */
3157 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
3158 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_TX_FAIL;
3159
3160 /* send the command */
3161 rStatus = wlanSendSetQueryCmd (
3162 prAdapter, /* prAdapter */
3163 CMD_ID_TDLS_CORE, /* ucCID */
3164 TRUE, /* fgSetQuery */
3165 FALSE, /* fgNeedResp */
3166 FALSE, /* fgIsOid */
3167 NULL,
3168 NULL, /* pfCmdTimeoutHandler */
3169 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
3170 (PUINT_8) prCmdContent, /* pucInfoBuffer */
3171 NULL, /* pvSetQueryBuffer */
3172 0 /* u4SetQueryBufferLen */
3173 );
3174
3175 if (rStatus != WLAN_STATUS_PENDING)
3176 {
3177 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
3178 __FUNCTION__));
3179 return TDLS_STATUS_RESOURCES;
3180 }
3181
3182 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
3183 return TDLS_STATUS_SUCCESS;
3184 }
3185
3186
3187
3188 /*----------------------------------------------------------------------------*/
3189 /*!
3190 * \brief This routine is called to send a TDLS action frame.
3191 *
3192 * \param[in] prAdapter Pointer to the Adapter structure
3193 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
3194 * \param[in] u4SetBufferLen The length of the set buffer
3195 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
3196 * bytes read from the set buffer. If the call failed due to invalid length of
3197 * the set buffer, returns the amount of storage needed.
3198 *
3199 * \retval TDLS_STATUS_xx
3200 *
3201 * EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC]
3202
3203 iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01
3204 */
3205 /*----------------------------------------------------------------------------*/
3206 static TDLS_STATUS
3207 TdlsTestTdlsFrameSend(
3208 ADAPTER_T *prAdapter,
3209 VOID *pvSetBuffer,
3210 UINT_32 u4SetBufferLen,
3211 UINT_32 *pu4SetInfoLen
3212 )
3213 {
3214 GLUE_INFO_T *prGlueInfo;
3215 PARAM_CUSTOM_TDLS_CMD_STRUC_T *prCmd;
3216 struct wireless_dev *prWdev;
3217
3218
3219 /* sanity check */
3220 ASSERT(prAdapter);
3221 ASSERT(pvSetBuffer);
3222 ASSERT(pu4SetInfoLen);
3223
3224 DBGLOG(TDLS, INFO, ("<tdls_fme> %s\n", __FUNCTION__));
3225
3226 if(u4SetBufferLen == 0)
3227 return TDLS_STATUS_INVALID_LENGTH;
3228
3229 /* allocate/init packet */
3230 prGlueInfo = (GLUE_INFO_T *)prAdapter->prGlueInfo;
3231 prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUC_T *)pvSetBuffer;
3232 prWdev = (struct wireless_dev *)prGlueInfo->prDevHandler->ieee80211_ptr;
3233
3234 TdlsexCfg80211TdlsMgmt(prWdev->wiphy,
3235 NULL,
3236 prCmd->arRspAddr,
3237 prCmd->ucFmeType,
3238 1,
3239 0,
3240 NULL, /* open/none */
3241 0);
3242
3243 return TDLS_STATUS_SUCCESS;
3244 }
3245
3246
3247 /*----------------------------------------------------------------------------*/
3248 /*! \brief This routine is called to skip tx fail status. So always success in tx done in firmware.
3249 *
3250 * \param[in] prAdapter Pointer to the Adapter structure
3251 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
3252 * \param[in] u4SetBufferLen The length of the set buffer
3253 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
3254 * bytes read from the set buffer. If the call failed due to invalid length of
3255 * the set buffer, returns the amount of storage needed.
3256 *
3257 * \retval TDLS_STATUS_xx
3258 *
3259 */
3260 /*----------------------------------------------------------------------------*/
3261 static TDLS_STATUS
3262 TdlsTestTxFailSkip(
3263 ADAPTER_T *prAdapter,
3264 VOID *pvSetBuffer,
3265 UINT_32 u4SetBufferLen,
3266 UINT_32 *pu4SetInfoLen
3267 )
3268 {
3269 TDLS_CMD_CORE_T *prCmdContent;
3270 WLAN_STATUS rStatus;
3271
3272
3273 /* init command buffer */
3274 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
3275 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TX_FAIL_SKIP;
3276
3277 /* send the command */
3278 rStatus = wlanSendSetQueryCmd (
3279 prAdapter, /* prAdapter */
3280 CMD_ID_TDLS_CORE, /* ucCID */
3281 TRUE, /* fgSetQuery */
3282 FALSE, /* fgNeedResp */
3283 FALSE, /* fgIsOid */
3284 NULL,
3285 NULL, /* pfCmdTimeoutHandler */
3286 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
3287 (PUINT_8) prCmdContent, /* pucInfoBuffer */
3288 NULL, /* pvSetQueryBuffer */
3289 0 /* u4SetQueryBufferLen */
3290 );
3291
3292 if (rStatus != WLAN_STATUS_PENDING)
3293 {
3294 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
3295 __FUNCTION__));
3296 return TDLS_STATUS_RESOURCES;
3297 }
3298
3299 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
3300 return TDLS_STATUS_SUCCESS;
3301 }
3302
3303
3304
3305 /*----------------------------------------------------------------------------*/
3306 /*! \brief This routine is called to skip to do keep alive function in firmware.
3307 *
3308 * \param[in] prAdapter Pointer to the Adapter structure
3309 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
3310 * \param[in] u4SetBufferLen The length of the set buffer
3311 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
3312 * bytes read from the set buffer. If the call failed due to invalid length of
3313 * the set buffer, returns the amount of storage needed.
3314 *
3315 * \retval TDLS_STATUS_xx
3316 *
3317 */
3318 /*----------------------------------------------------------------------------*/
3319 static TDLS_STATUS
3320 TdlsTestKeepAliveSkip(
3321 ADAPTER_T *prAdapter,
3322 VOID *pvSetBuffer,
3323 UINT_32 u4SetBufferLen,
3324 UINT_32 *pu4SetInfoLen
3325 )
3326 {
3327 TDLS_CMD_CORE_T *prCmdContent;
3328 WLAN_STATUS rStatus;
3329
3330
3331 /* init command buffer */
3332 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
3333 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_KEEP_ALIVE_SKIP;
3334
3335 /* send the command */
3336 rStatus = wlanSendSetQueryCmd (
3337 prAdapter, /* prAdapter */
3338 CMD_ID_TDLS_CORE, /* ucCID */
3339 TRUE, /* fgSetQuery */
3340 FALSE, /* fgNeedResp */
3341 FALSE, /* fgIsOid */
3342 NULL,
3343 NULL, /* pfCmdTimeoutHandler */
3344 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
3345 (PUINT_8) prCmdContent, /* pucInfoBuffer */
3346 NULL, /* pvSetQueryBuffer */
3347 0 /* u4SetQueryBufferLen */
3348 );
3349
3350 if (rStatus != WLAN_STATUS_PENDING)
3351 {
3352 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
3353 __FUNCTION__));
3354 return TDLS_STATUS_RESOURCES;
3355 }
3356
3357 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
3358 return TDLS_STATUS_SUCCESS;
3359 }
3360
3361
3362 /*----------------------------------------------------------------------------*/
3363 /*! \brief This routine is called to skip channel switch timeout.
3364 *
3365 * \param[in] prAdapter Pointer to the Adapter structure
3366 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
3367 * \param[in] u4SetBufferLen The length of the set buffer
3368 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
3369 * bytes read from the set buffer. If the call failed due to invalid length of
3370 * the set buffer, returns the amount of storage needed.
3371 *
3372 * \retval TDLS_STATUS_xx
3373 *
3374 */
3375 /*----------------------------------------------------------------------------*/
3376 static TDLS_STATUS
3377 TdlsTestChSwTimeoutSkip(
3378 ADAPTER_T *prAdapter,
3379 VOID *pvSetBuffer,
3380 UINT_32 u4SetBufferLen,
3381 UINT_32 *pu4SetInfoLen
3382 )
3383 {
3384 TDLS_CMD_CORE_T *prCmdContent;
3385 WLAN_STATUS rStatus;
3386
3387
3388 /* init command buffer */
3389 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
3390 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_TIMEOUT_SKIP;
3391
3392 /* send the command */
3393 rStatus = wlanSendSetQueryCmd (
3394 prAdapter, /* prAdapter */
3395 CMD_ID_TDLS_CORE, /* ucCID */
3396 TRUE, /* fgSetQuery */
3397 FALSE, /* fgNeedResp */
3398 FALSE, /* fgIsOid */
3399 NULL,
3400 NULL, /* pfCmdTimeoutHandler */
3401 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
3402 (PUINT_8) prCmdContent, /* pucInfoBuffer */
3403 NULL, /* pvSetQueryBuffer */
3404 0 /* u4SetQueryBufferLen */
3405 );
3406
3407 if (rStatus != WLAN_STATUS_PENDING)
3408 {
3409 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
3410 __FUNCTION__));
3411 return TDLS_STATUS_RESOURCES;
3412 }
3413
3414 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
3415 return TDLS_STATUS_SUCCESS;
3416 }
3417
3418
3419 /*----------------------------------------------------------------------------*/
3420 /*! \brief This routine is called to skip scan request.
3421 *
3422 * \param[in] prAdapter Pointer to the Adapter structure
3423 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
3424 * \param[in] u4SetBufferLen The length of the set buffer
3425 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
3426 * bytes read from the set buffer. If the call failed due to invalid length of
3427 * the set buffer, returns the amount of storage needed.
3428 *
3429 * \retval TDLS_STATUS_xx
3430 *
3431 */
3432 /*----------------------------------------------------------------------------*/
3433 static TDLS_STATUS
3434 TdlsTestScanSkip(
3435 ADAPTER_T *prAdapter,
3436 VOID *pvSetBuffer,
3437 UINT_32 u4SetBufferLen,
3438 UINT_32 *pu4SetInfoLen
3439 )
3440 {
3441 TDLS_CMD_CORE_T *prCmdContent;
3442 WLAN_STATUS rStatus;
3443
3444
3445 /* init command buffer */
3446 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
3447 prCmdContent->u4Command = TDLS_CORE_CMD_TEST_SCAN_SKIP;
3448
3449 /* send the command */
3450 rStatus = wlanSendSetQueryCmd (
3451 prAdapter, /* prAdapter */
3452 CMD_ID_TDLS_CORE, /* ucCID */
3453 TRUE, /* fgSetQuery */
3454 FALSE, /* fgNeedResp */
3455 FALSE, /* fgIsOid */
3456 NULL,
3457 NULL, /* pfCmdTimeoutHandler */
3458 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
3459 (PUINT_8) prCmdContent, /* pucInfoBuffer */
3460 NULL, /* pvSetQueryBuffer */
3461 0 /* u4SetQueryBufferLen */
3462 );
3463
3464 if (rStatus != WLAN_STATUS_PENDING)
3465 {
3466 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
3467 __FUNCTION__));
3468 return TDLS_STATUS_RESOURCES;
3469 }
3470
3471 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
3472 return TDLS_STATUS_SUCCESS;
3473 }
3474
3475
3476 #endif /* TDLS_CFG_CMD_TEST */
3477
3478
3479 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
3480 /*----------------------------------------------------------------------------*/
3481 /*! \brief This routine is called to send a TDLS event to supplicant.
3482 *
3483 * \param[in] prGlueInfo Pointer to the Adapter structure
3484 * \param[in] prInBuf A pointer to the command string buffer
3485 * \param[in] u4InBufLen The length of the buffer
3486 * \param[out] None
3487 *
3488 * \retval None
3489 *
3490 */
3491 /*----------------------------------------------------------------------------*/
3492 void cfg80211_tdls_oper_request(
3493 struct net_device *dev,
3494 const u8 *peer,
3495 u16 oper,
3496 u16 reason_code,
3497 gfp_t gfp
3498 )
3499 {
3500 GLUE_INFO_T *prGlueInfo;
3501 ADAPTER_T *prAdapter;
3502 struct sk_buff *prMsduInfo;
3503 UINT_8 *pPkt;
3504 UINT_32 u4PktLen;
3505
3506
3507 /* sanity check */
3508 if ((dev == NULL) || (peer == NULL))
3509 return; /* shall not be here */
3510
3511 DBGLOG(TDLS, INFO,
3512 ("<tdls_fme> %s: Oper=%d ReasonCode=%d from "MACSTR"\n",
3513 __FUNCTION__, oper, reason_code, MAC2STR(peer)));
3514
3515 /* init */
3516 prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev));
3517 prAdapter = prGlueInfo->prAdapter;
3518 u4PktLen = 0;
3519
3520 /* allocate/init packet */
3521 prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt);
3522 if (prMsduInfo == NULL) {
3523 DBGLOG(TDLS, ERROR, ("<tdls_cmd> %s: allocate pkt fail\n", __FUNCTION__));
3524 return;
3525 }
3526 prMsduInfo->dev = dev;
3527
3528 /* make up frame content */
3529 /* 1. 802.3 header */
3530 kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN);
3531 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
3532 kalMemCopy(pPkt, peer, TDLS_FME_MAC_ADDR_LEN);
3533 LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN);
3534 *(UINT_16 *)pPkt = htons(TDLS_FRM_PROT_TYPE);
3535 LR_TDLS_FME_FIELD_FILL(2);
3536
3537 /* 2. payload type */
3538 *pPkt = TDLS_FRM_PAYLOAD_TYPE;
3539 LR_TDLS_FME_FIELD_FILL(1);
3540
3541 /* 3. Frame Formation - (1) Category */
3542 *pPkt = TDLS_FRM_CATEGORY;
3543 LR_TDLS_FME_FIELD_FILL(1);
3544
3545 /* 3. Frame Formation - (2) Action */
3546 *pPkt = TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT;
3547 LR_TDLS_FME_FIELD_FILL(1);
3548
3549 /* 3. Frame Formation - (3) Operation */
3550 *pPkt = oper;
3551 LR_TDLS_FME_FIELD_FILL(1);
3552
3553 /* 3. Frame Formation - (4) Reason Code */
3554 *pPkt = reason_code;
3555 *(pPkt+1) = 0x00;
3556 LR_TDLS_FME_FIELD_FILL(2);
3557
3558 /* 3. Frame Formation - (5) Peer MAC */
3559 kalMemCopy(pPkt, peer, 6);
3560 LR_TDLS_FME_FIELD_FILL(6);
3561
3562 /* 4. Update packet length */
3563 prMsduInfo->len = u4PktLen;
3564 dumpMemory8(ANDROID_LOG_INFO, prMsduInfo->data, u4PktLen);
3565
3566 /* pass to OS */
3567 TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo);
3568 }
3569 #endif /* LINUX_VERSION_CODE */
3570
3571
3572 /*----------------------------------------------------------------------------*/
3573 /*! \brief This routine is called to configure channel switch parameters.
3574 *
3575 * \param[in] prAdapter Pointer to the Adapter structure
3576 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
3577 * \param[in] u4SetBufferLen The length of the set buffer
3578 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
3579 * bytes read from the set buffer. If the call failed due to invalid length of
3580 * the set buffer, returns the amount of storage needed.
3581 *
3582 * \retval TDLS_STATUS_xx
3583 *
3584 */
3585 /*----------------------------------------------------------------------------*/
3586 static TDLS_STATUS
3587 TdlsChSwConf(
3588 ADAPTER_T *prAdapter,
3589 VOID *pvSetBuffer,
3590 UINT_32 u4SetBufferLen,
3591 UINT_32 *pu4SetInfoLen
3592 )
3593 {
3594 TDLS_CMD_CORE_T *prCmdContent;
3595 WLAN_STATUS rStatus;
3596
3597
3598 /* init command buffer */
3599 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
3600 prCmdContent->u4Command = TDLS_CORE_CMD_CHSW_CONF;
3601
3602 /* send the command */
3603 rStatus = wlanSendSetQueryCmd (
3604 prAdapter, /* prAdapter */
3605 CMD_ID_TDLS_CORE, /* ucCID */
3606 TRUE, /* fgSetQuery */
3607 FALSE, /* fgNeedResp */
3608 FALSE, /* fgIsOid */
3609 NULL,
3610 NULL, /* pfCmdTimeoutHandler */
3611 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
3612 (PUINT_8) prCmdContent, /* pucInfoBuffer */
3613 NULL, /* pvSetQueryBuffer */
3614 0 /* u4SetQueryBufferLen */
3615 );
3616
3617 if (rStatus != WLAN_STATUS_PENDING)
3618 {
3619 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
3620 __FUNCTION__));
3621 return TDLS_STATUS_RESOURCES;
3622 }
3623
3624 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
3625 return TDLS_STATUS_SUCCESS;
3626 }
3627
3628
3629 /*----------------------------------------------------------------------------*/
3630 /*! \brief This routine is called to update channel switch parameters.
3631 *
3632 * \param[in] prGlueInfo Pointer to the Adapter structure
3633 * \param[in] prInBuf A pointer to the command string buffer
3634 * \param[in] u4InBufLen The length of the buffer
3635 * \param[out] None
3636 *
3637 * \retval None
3638 *
3639 * EX: iwpriv wlan0 set_str_cmd 0_9_[TDLS Peer MAC]_
3640 [NetworkTypeIndex]_[1 (Enable) or (0) Disable]_[1 (Start) or 0 (Stop)]_
3641 [RegClass]_[Chan]_[SecChanOff]_[1 (Reqular) or (0) One Shot]
3642
3643 RegulatoryClass: TODO (reference to Annex I of 802.11n spec.)
3644 Secondary Channel Offset: 0 (SCN - no secondary channel)
3645 1 (SCA - secondary channel above)
3646 2 (SCB - secondary channel below)
3647 SwitchTime: units of microseconds
3648
3649 iwpriv wlan0 set_str_cmd 0_9_00:11:22:33:44:01_0_1_0_0_1_0_0
3650 */
3651 /*----------------------------------------------------------------------------*/
3652 static void
3653 TdlsCmdChSwConf(
3654 P_GLUE_INFO_T prGlueInfo,
3655 UINT_8 *prInBuf,
3656 UINT_32 u4InBufLen
3657 )
3658 {
3659 WLAN_STATUS rStatus;
3660 TDLS_CMD_CORE_T rCmd;
3661 UINT_32 u4BufLen;
3662
3663
3664 /* parse arguments */
3665 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
3666
3667 rCmd.Content.rCmdChSwConf.ucNetTypeIndex = \
3668 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3669 rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = \
3670 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3671 rCmd.Content.rCmdChSwConf.fgIsChSwStarted = \
3672 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3673 rCmd.Content.rCmdChSwConf.ucRegClass = \
3674 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3675 rCmd.Content.rCmdChSwConf.ucTargetChan = \
3676 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3677 rCmd.Content.rCmdChSwConf.ucSecChanOff = \
3678 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3679 rCmd.Content.rCmdChSwConf.fgIsChSwRegular = \
3680 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3681
3682 DBGLOG(TDLS, INFO,
3683 ("%s: "MACSTR" ucNetTypeIndex=%d, fgIsChSwEnabled=%d, fgIsChSwStarted=%d "
3684 "RegClass=%d, TargetChan=%d, SecChanOff=%d, Regular=%d\n",
3685 __FUNCTION__, MAC2STR(rCmd.aucPeerMac),
3686 rCmd.Content.rCmdChSwConf.ucNetTypeIndex,
3687 rCmd.Content.rCmdChSwConf.fgIsChSwEnabled,
3688 rCmd.Content.rCmdChSwConf.fgIsChSwStarted,
3689 rCmd.Content.rCmdChSwConf.ucRegClass,
3690 rCmd.Content.rCmdChSwConf.ucTargetChan,
3691 rCmd.Content.rCmdChSwConf.ucSecChanOff,
3692 rCmd.Content.rCmdChSwConf.fgIsChSwRegular));
3693
3694 /* command to do this */
3695 rStatus = kalIoctl(prGlueInfo,
3696 TdlsChSwConf,
3697 &rCmd,
3698 sizeof(rCmd),
3699 FALSE,
3700 FALSE,
3701 FALSE,
3702 FALSE,
3703 &u4BufLen);
3704
3705 if (rStatus != WLAN_STATUS_SUCCESS)
3706 {
3707 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
3708 return;
3709 }
3710 }
3711
3712
3713 /*----------------------------------------------------------------------------*/
3714 /*! \brief This routine is called to display TDLS related informations.
3715 *
3716 * \param[in] prGlueInfo Pointer to the Adapter structure
3717 * \param[in] prInBuf A pointer to the command string buffer
3718 * \param[in] u4InBufLen The length of the buffer
3719 * \param[out] None
3720 *
3721 * \retval None
3722 *
3723 * EX: iwpriv wlan0 set_str_cmd 0_18_[Peer MAC]_[Network Interface ID]_[IsClear]
3724
3725 Network Interface ID: reference to ENUM_NETWORK_TYPE_INDEX_T
3726
3727 typedef enum _ENUM_NETWORK_TYPE_INDEX_T {
3728 NETWORK_TYPE_AIS_INDEX = 0,
3729 NETWORK_TYPE_P2P_INDEX,
3730 NETWORK_TYPE_BOW_INDEX,
3731 NETWORK_TYPE_INDEX_NUM
3732 } ENUM_NETWORK_TYPE_INDEX_T;
3733
3734 iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0
3735 */
3736 /*----------------------------------------------------------------------------*/
3737 static void
3738 TdlsCmdInfoDisplay(
3739 GLUE_INFO_T *prGlueInfo,
3740 UINT_8 *prInBuf,
3741 UINT_32 u4InBufLen
3742 )
3743 {
3744 WLAN_STATUS rStatus;
3745 TDLS_CMD_CORE_T rCmd;
3746 UINT_32 u4BufLen;
3747
3748
3749 /* parse arguments */
3750 kalMemZero(&rCmd, sizeof(rCmd));
3751
3752 CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac);
3753 rCmd.ucNetTypeIndex = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3754 rCmd.Content.rCmdInfoDisplay.fgIsToClearAllHistory = \
3755 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3756
3757 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: Command PeerMac="MACSTR" in BSS%u\n",
3758 __FUNCTION__, MAC2STR(rCmd.aucPeerMac), rCmd.ucNetTypeIndex));
3759
3760 /* command to do this */
3761 rStatus = kalIoctl(prGlueInfo,
3762 TdlsInfoDisplay,
3763 &rCmd,
3764 sizeof(rCmd),
3765 FALSE,
3766 FALSE,
3767 FALSE,
3768 FALSE,
3769 &u4BufLen);
3770
3771 if (rStatus != WLAN_STATUS_SUCCESS)
3772 {
3773 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
3774 return;
3775 }
3776 }
3777
3778
3779 /*----------------------------------------------------------------------------*/
3780 /*! \brief This routine is called to display key related informations.
3781 *
3782 * \param[in] prGlueInfo Pointer to the Adapter structure
3783 * \param[in] prInBuf A pointer to the command string buffer
3784 * \param[in] u4InBufLen The length of the buffer
3785 * \param[out] None
3786 *
3787 * \retval None
3788 *
3789 * EX: iwpriv wlan0 set_str_cmd 0_20
3790
3791 iwpriv wlan0 set_str_cmd 0_20
3792 */
3793 /*----------------------------------------------------------------------------*/
3794 static void
3795 TdlsCmdKeyInfoDisplay(
3796 GLUE_INFO_T *prGlueInfo,
3797 UINT_8 *prInBuf,
3798 UINT_32 u4InBufLen
3799 )
3800 {
3801 WLAN_STATUS rStatus;
3802 TDLS_CMD_CORE_T rCmd;
3803 UINT_32 u4BufLen;
3804
3805
3806 /* parse arguments */
3807 kalMemZero(&rCmd, sizeof(rCmd));
3808
3809 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s\n", __FUNCTION__));
3810
3811 /* command to do this */
3812 rStatus = kalIoctl(prGlueInfo,
3813 TdlsKeyInfoDisplay,
3814 &rCmd,
3815 sizeof(rCmd),
3816 FALSE,
3817 FALSE,
3818 FALSE,
3819 FALSE,
3820 &u4BufLen);
3821
3822 if (rStatus != WLAN_STATUS_SUCCESS)
3823 {
3824 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
3825 return;
3826 }
3827 }
3828
3829
3830 /*----------------------------------------------------------------------------*/
3831 /*! \brief This routine is called to update MIB parameters.
3832 *
3833 * \param[in] prGlueInfo Pointer to the Adapter structure
3834 * \param[in] prInBuf A pointer to the command string buffer
3835 * \param[in] u4InBufLen The length of the buffer
3836 * \param[out] None
3837 *
3838 * \retval None
3839 *
3840 * EX: iwpriv wlan0 set_str_cmd 0_6_[TdlsEn]_[UapsdEn]_[PsmEn]_[PtiWin]_[CWCap]_
3841 [AckMisRetry]_[RspTimeout]_[CWPbDelay]_[DRWin]_[LowestAcInt]
3842
3843 iwpriv wlan0 set_str_cmd 0_6_1_1_0_1_1_3_5_1000_2_1
3844
3845 reference to TDLS_CMD_CORE_MIB_PARAM_UPDATE_T
3846 */
3847 /*----------------------------------------------------------------------------*/
3848 static void
3849 TdlsCmdMibParamUpdate(
3850 P_GLUE_INFO_T prGlueInfo,
3851 UINT_8 *prInBuf,
3852 UINT_32 u4InBufLen
3853 )
3854 {
3855 WLAN_STATUS rStatus;
3856 TDLS_CMD_CORE_T rCmd;
3857 UINT_32 u4BufLen;
3858
3859
3860 /* reset */
3861 kalMemZero(&rCmd, sizeof(rCmd));
3862
3863 /* parse arguments */
3864 rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented = \
3865 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3866 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated = \
3867 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3868 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated = \
3869 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3870 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow = \
3871 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3872 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated = \
3873 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3874 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit = \
3875 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3876 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout = \
3877 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3878 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay = \
3879 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3880 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow = \
3881 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3882 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval = \
3883 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3884
3885 DBGLOG(TDLS, INFO, ("<tdls_cmd> MIB param = %d %d %d %d %d %d %d %d %d %d \n",
3886 rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented,
3887 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated,
3888 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated,
3889 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow,
3890 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated,
3891 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit,
3892 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout,
3893 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay,
3894 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow,
3895 rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval));
3896
3897 /* command to do this */
3898 rStatus = kalIoctl(prGlueInfo,
3899 TdlsMibParamUpdate,
3900 &rCmd,
3901 sizeof(rCmd),
3902 FALSE,
3903 FALSE,
3904 FALSE,
3905 FALSE,
3906 &u4BufLen);
3907
3908 if (rStatus != WLAN_STATUS_SUCCESS)
3909 {
3910 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
3911 return;
3912 }
3913 }
3914
3915
3916 /*----------------------------------------------------------------------------*/
3917 /*! \brief This routine is called to update setup parameters.
3918 *
3919 * \param[in] prGlueInfo Pointer to the Adapter structure
3920 * \param[in] prInBuf A pointer to the command string buffer
3921 * \param[in] u4InBufLen The length of the buffer
3922 * \param[out] None
3923 *
3924 * \retval None
3925 *
3926 * EX: iwpriv wlan0 set_str_cmd 0_17_[20/40 Support]
3927
3928 iwpriv wlan0 set_str_cmd 0_17_1
3929 */
3930 /*----------------------------------------------------------------------------*/
3931 static void
3932 TdlsCmdSetupConf(
3933 P_GLUE_INFO_T prGlueInfo,
3934 UINT_8 *prInBuf,
3935 UINT_32 u4InBufLen
3936 )
3937 {
3938 WLAN_STATUS rStatus;
3939 TDLS_CMD_CORE_T rCmd;
3940 UINT_32 u4BufLen;
3941
3942
3943 /* parse arguments */
3944 kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
3945
3946 rCmd.Content.rCmdSetupConf.fgIs2040Supported = \
3947 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
3948
3949 DBGLOG(TDLS, INFO, ("%s: rCmdSetupConf=%d\n",
3950 __FUNCTION__, rCmd.Content.rCmdSetupConf.fgIs2040Supported));
3951
3952 /* command to do this */
3953 prGlueInfo->rTdlsLink.fgIs2040Sup = rCmd.Content.rCmdSetupConf.fgIs2040Supported;
3954
3955 rStatus = kalIoctl(prGlueInfo,
3956 TdlsSetupConf,
3957 &rCmd,
3958 sizeof(rCmd),
3959 FALSE,
3960 FALSE,
3961 FALSE,
3962 FALSE,
3963 &u4BufLen);
3964
3965 if (rStatus != WLAN_STATUS_SUCCESS)
3966 {
3967 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
3968 return;
3969 }
3970 }
3971
3972
3973 /*----------------------------------------------------------------------------*/
3974 /*! \brief This routine is called to update UAPSD parameters.
3975 *
3976 * \param[in] prGlueInfo Pointer to the Adapter structure
3977 * \param[in] prInBuf A pointer to the command string buffer
3978 * \param[in] u4InBufLen The length of the buffer
3979 * \param[out] None
3980 *
3981 * \retval None
3982 *
3983 * EX: iwpriv wlan0 set_str_cmd 0_8_[SP timeout skip]_[PTI timeout skip]
3984
3985 iwpriv wlan0 set_str_cmd 0_8_1_1
3986 */
3987 /*----------------------------------------------------------------------------*/
3988 static void
3989 TdlsCmdUapsdConf(
3990 P_GLUE_INFO_T prGlueInfo,
3991 UINT_8 *prInBuf,
3992 UINT_32 u4InBufLen
3993 )
3994 {
3995 WLAN_STATUS rStatus;
3996 TDLS_CMD_CORE_T rCmd;
3997 UINT_32 u4BufLen;
3998
3999
4000 /* parse arguments */
4001 kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac));
4002
4003 /* UAPSD Service Period */
4004 rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip = \
4005 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
4006 rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip = \
4007 CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
4008 /* PTI Service Period */
4009 fgIsPtiTimeoutSkip = rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip;
4010
4011 DBGLOG(TDLS, INFO, ("%s: fgIsSpTimeoutSkip=%d, fgIsPtiTimeoutSkip=%d\n",
4012 __FUNCTION__, rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip,
4013 fgIsPtiTimeoutSkip));
4014
4015 /* command to do this */
4016 rStatus = kalIoctl(prGlueInfo,
4017 TdlsUapsdConf,
4018 &rCmd,
4019 sizeof(rCmd),
4020 FALSE,
4021 FALSE,
4022 FALSE,
4023 FALSE,
4024 &u4BufLen);
4025
4026 if (rStatus != WLAN_STATUS_SUCCESS)
4027 {
4028 DBGLOG(TDLS, ERROR, ("%s kalIoctl fail:%x\n", __FUNCTION__, rStatus));
4029 return;
4030 }
4031 }
4032
4033
4034 /*----------------------------------------------------------------------------*/
4035 /*! \brief This routine is called to display TDLS all information.
4036 *
4037 * \param[in] prAdapter Pointer to the Adapter structure
4038 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
4039 * \param[in] u4SetBufferLen The length of the set buffer
4040 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
4041 * bytes read from the set buffer. If the call failed due to invalid length of
4042 * the set buffer, returns the amount of storage needed.
4043 *
4044 * \retval TDLS_STATUS_xx
4045 *
4046 * iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0
4047 *
4048 */
4049 /*----------------------------------------------------------------------------*/
4050 static TDLS_STATUS
4051 TdlsInfoDisplay(
4052 ADAPTER_T *prAdapter,
4053 VOID *pvSetBuffer,
4054 UINT_32 u4SetBufferLen,
4055 UINT_32 *pu4SetInfoLen
4056 )
4057 {
4058 GLUE_INFO_T *prGlueInfo;
4059 TDLS_CMD_CORE_T *prCmdContent;
4060 STA_RECORD_T *prStaRec;
4061 TDLS_INFO_LINK_T *prLink;
4062 UINT32 u4StartIdx;
4063 UINT32 u4PeerNum;
4064 BOOLEAN fgIsListAll;
4065 UINT8 ucMacZero[6];
4066 UINT32 u4HisIdx;
4067 UINT8 ucNetTypeIndex;
4068
4069
4070 /* init */
4071 prGlueInfo = prAdapter->prGlueInfo;
4072 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
4073 u4StartIdx = 0;
4074 u4PeerNum = 1;
4075 fgIsListAll = TRUE;
4076 kalMemZero(ucMacZero, sizeof(ucMacZero));
4077 ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX;
4078
4079 /* display common information */
4080 DBGLOG(TDLS, TRACE, ("TDLS common:\n"));
4081 DBGLOG(TDLS, TRACE, ("\t\trFreeSwRfbList=%u\n",
4082 (UINT32)prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem));
4083 DBGLOG(TDLS, TRACE, ("\t\tjiffies=%u %ums (HZ=%d)\n", (UINT32)jiffies,
4084 (UINT32)kalGetTimeTick(), HZ));
4085
4086 /* display disconnection history information */
4087 DBGLOG(TDLS, TRACE, ("TDLS link history: %d\n",
4088 prGlueInfo->rTdlsLink.u4LinkIdx));
4089
4090 for(u4HisIdx = prGlueInfo->rTdlsLink.u4LinkIdx+1;
4091 u4HisIdx < TDLS_LINK_HISTORY_MAX;
4092 u4HisIdx++)
4093 {
4094 prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx];
4095
4096 if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0)
4097 continue; /* skip all zero */
4098
4099 DBGLOG(TDLS, TRACE,
4100 ("\t\t%d. "MACSTR": jiffies start(%lu %ums) jiffies end(%lu %ums) "
4101 "Reason(%u) fromUs(%u) Dup(%u) HT(%u)\n",
4102 u4HisIdx,
4103 MAC2STR(prLink->aucPeerMac),
4104 prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start),
4105 prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end),
4106 prLink->ucReasonCode,
4107 prLink->fgIsFromUs,
4108 prLink->ucDupCount,
4109 (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)));
4110
4111 if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)
4112 {
4113 DBGLOG(TDLS, TRACE,
4114 ("\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n",
4115 prLink->ucHtBa[0], prLink->ucHtBa[1],
4116 prLink->ucHtBa[2], prLink->ucHtBa[3],
4117 prLink->ucHtBa[4], prLink->ucHtBa[5],
4118 prLink->ucHtBa[6], prLink->ucHtBa[7]));
4119 }
4120 }
4121 for(u4HisIdx = 0;
4122 u4HisIdx <= prGlueInfo->rTdlsLink.u4LinkIdx;
4123 u4HisIdx++)
4124 {
4125 prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx];
4126
4127 if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0)
4128 continue; /* skip all zero, use continue, not break */
4129
4130 DBGLOG(TDLS, TRACE,
4131 ("\t\t%d. "MACSTR": jiffies start(%lu %ums) jiffies end(%lu %ums) "
4132 "Reason(%u) fromUs(%u) Dup(%u) HT(%u)\n",
4133 u4HisIdx,
4134 MAC2STR(prLink->aucPeerMac),
4135 prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start),
4136 prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end),
4137 prLink->ucReasonCode,
4138 prLink->fgIsFromUs,
4139 prLink->ucDupCount,
4140 (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)));
4141
4142 if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)
4143 {
4144 DBGLOG(TDLS, TRACE,
4145 ("\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n",
4146 prLink->ucHtBa[0], prLink->ucHtBa[1],
4147 prLink->ucHtBa[2], prLink->ucHtBa[3],
4148 prLink->ucHtBa[4], prLink->ucHtBa[5],
4149 prLink->ucHtBa[6], prLink->ucHtBa[7]));
4150 }
4151 }
4152 DBGLOG(TDLS, TRACE, ("\n"));
4153
4154 /* display link information */
4155 if (prCmdContent != NULL)
4156 {
4157 if (kalMemCmp(prCmdContent->aucPeerMac, ucMacZero, 6) != 0)
4158 {
4159 prStaRec = cnmGetStaRecByAddress(prAdapter,
4160 prCmdContent->ucNetTypeIndex, prCmdContent->aucPeerMac);
4161 if (prStaRec == NULL)
4162 fgIsListAll = TRUE;
4163 }
4164
4165 ucNetTypeIndex = prCmdContent->ucNetTypeIndex;
4166 }
4167
4168 while(1)
4169 {
4170 if (fgIsListAll == TRUE)
4171 {
4172 /* list all TDLS peers */
4173 prStaRec = cnmStaTheTypeGet(prAdapter, ucNetTypeIndex,
4174 STA_TYPE_TDLS_PEER, &u4StartIdx);
4175 if (prStaRec == NULL)
4176 break;
4177 }
4178
4179 DBGLOG(TDLS, TRACE, ("-------- TDLS %d: 0x"MACSTR"\n",
4180 u4PeerNum, MAC2STR(prStaRec->aucMacAddr)));
4181 DBGLOG(TDLS, TRACE, ("\t\t\t State %d, PM %d, Cap 0x%x\n",
4182 prStaRec->ucStaState, prStaRec->fgIsInPS, prStaRec->u2CapInfo));
4183 DBGLOG(TDLS, TRACE, ("\t\t\t SetupDisable %d, ChSwDisable %d\n",
4184 prStaRec->fgTdlsIsProhibited, prStaRec->fgTdlsIsChSwProhibited));
4185
4186 if (fgIsListAll == FALSE)
4187 break; /* only list one */
4188 }
4189
4190 /* check if we need to clear all histories */
4191 if ((prCmdContent != NULL) &&
4192 (prCmdContent->Content.rCmdInfoDisplay.fgIsToClearAllHistory == TRUE))
4193 {
4194 kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink));
4195 prGlueInfo->rTdlsLink.u4LinkIdx = TDLS_LINK_HISTORY_MAX-1;
4196 }
4197
4198 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
4199 return TDLS_STATUS_SUCCESS;
4200 }
4201
4202
4203 /*----------------------------------------------------------------------------*/
4204 /*! \brief This routine is called to display key information.
4205 *
4206 * \param[in] prAdapter Pointer to the Adapter structure
4207 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
4208 * \param[in] u4SetBufferLen The length of the set buffer
4209 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
4210 * bytes read from the set buffer. If the call failed due to invalid length of
4211 * the set buffer, returns the amount of storage needed.
4212 *
4213 * \retval TDLS_STATUS_xx
4214 *
4215 */
4216 /*----------------------------------------------------------------------------*/
4217 static TDLS_STATUS
4218 TdlsKeyInfoDisplay(
4219 ADAPTER_T *prAdapter,
4220 VOID *pvSetBuffer,
4221 UINT_32 u4SetBufferLen,
4222 UINT_32 *pu4SetInfoLen
4223 )
4224 {
4225 TDLS_CMD_CORE_T *prCmdContent;
4226 WLAN_STATUS rStatus;
4227
4228
4229 /* init command buffer */
4230 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
4231 prCmdContent->u4Command = TDLS_CORE_CMD_KEY_INFO;
4232
4233 /* send the command */
4234 rStatus = wlanSendSetQueryCmd (
4235 prAdapter, /* prAdapter */
4236 CMD_ID_TDLS_CORE, /* ucCID */
4237 TRUE, /* fgSetQuery */
4238 FALSE, /* fgNeedResp */
4239 FALSE, /* fgIsOid */
4240 NULL,
4241 NULL, /* pfCmdTimeoutHandler */
4242 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
4243 (PUINT_8) prCmdContent, /* pucInfoBuffer */
4244 NULL, /* pvSetQueryBuffer */
4245 0 /* u4SetQueryBufferLen */
4246 );
4247
4248 if (rStatus != WLAN_STATUS_PENDING)
4249 {
4250 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
4251 __FUNCTION__));
4252 return TDLS_STATUS_RESOURCES;
4253 }
4254
4255 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
4256 return TDLS_STATUS_SUCCESS;
4257 }
4258
4259
4260 /*----------------------------------------------------------------------------*/
4261 /*! \brief This routine is called to record a disconnection event.
4262 *
4263 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure
4264 * \param[in] fgIsTearDown TRUE: the link is torn down
4265 * \param[in] pucPeerMac Pointer to the MAC of the TDLS peer
4266 * \param[in] fgIsFromUs TRUE: tear down is from us
4267 * \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE)
4268 *
4269 * \retval none
4270 */
4271 /*----------------------------------------------------------------------------*/
4272 static VOID
4273 TdlsLinkHistoryRecord(
4274 GLUE_INFO_T *prGlueInfo,
4275 BOOLEAN fgIsTearDown,
4276 UINT8 *pucPeerMac,
4277 BOOLEAN fgIsFromUs,
4278 UINT16 u2ReasonCode,
4279 VOID *prOthers
4280 )
4281 {
4282 TDLS_INFO_LINK_T *prLink;
4283
4284
4285 DBGLOG(TDLS, INFO,
4286 ("<tdls_evt> %s: record history for "MACSTR" %d %d %d %d\n",
4287 __FUNCTION__, MAC2STR(pucPeerMac), prGlueInfo->rTdlsLink.u4LinkIdx,
4288 fgIsTearDown, fgIsFromUs, u2ReasonCode));
4289
4290 /* check duplicate one */
4291 if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX)
4292 {
4293 DBGLOG(TDLS, ERROR,
4294 ("<tdls_evt> %s: u4LinkIdx >= TDLS_LINK_HISTORY_MAX\n",
4295 __FUNCTION__));
4296
4297 /* reset to 0 */
4298 prGlueInfo->rTdlsLink.u4LinkIdx = 0;
4299 }
4300
4301 prLink = &prGlueInfo->rTdlsLink.rLinkHistory[\
4302 prGlueInfo->rTdlsLink.u4LinkIdx];
4303
4304 if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) == 0)
4305 {
4306 if ((prLink->ucReasonCode == u2ReasonCode) &&
4307 (prLink->fgIsFromUs == fgIsFromUs))
4308 {
4309 /* same Peer MAC, Reason Code, Trigger source */
4310 if (fgIsTearDown == TRUE)
4311 {
4312 if (prLink->jiffies_end != 0)
4313 {
4314 /* already torn down */
4315 prLink->ucDupCount ++;
4316 return;
4317 }
4318 }
4319 else
4320 {
4321 /* already built */
4322 prLink->ucDupCount ++;
4323 return;
4324 }
4325 }
4326 }
4327
4328 /* search old entry */
4329 if (fgIsTearDown == TRUE)
4330 {
4331 /* TODO: need to search all entries to find it if we support multiple TDLS link design */
4332 if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0)
4333 {
4334 /* error! can not find the link entry */
4335 DBGLOG(TDLS, INFO,
4336 ("<tdls_evt> %s: cannot find the same entry!!!\n",
4337 __FUNCTION__));
4338 return;
4339 }
4340
4341 prLink->jiffies_end = jiffies;
4342 prLink->ucReasonCode = (UINT8)u2ReasonCode;
4343 prLink->fgIsFromUs = fgIsFromUs;
4344 }
4345 else
4346 {
4347 /* record new one */
4348 prGlueInfo->rTdlsLink.u4LinkIdx ++;
4349 if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX)
4350 prGlueInfo->rTdlsLink.u4LinkIdx = 0;
4351
4352 prLink = &prGlueInfo->rTdlsLink.rLinkHistory[\
4353 prGlueInfo->rTdlsLink.u4LinkIdx];
4354
4355 prLink->jiffies_start = jiffies;
4356 prLink->jiffies_end = 0;
4357 kalMemCopy(&prLink->aucPeerMac, pucPeerMac, 6);
4358 prLink->ucReasonCode = 0;
4359 prLink->fgIsFromUs = (UINT8)fgIsFromUs;
4360 prLink->ucDupCount = 0;
4361
4362 if (prOthers != NULL)
4363 {
4364 /* record other parameters */
4365 TDLS_LINK_HIS_OTHERS_T *prHisOthers;
4366 prHisOthers = (TDLS_LINK_HIS_OTHERS_T *)prOthers;
4367 if (prHisOthers->fgIsHt == TRUE)
4368 prLink->ucHtCap |= TDLS_INFO_LINK_HT_CAP_SUP;
4369 }
4370 }
4371 }
4372
4373
4374 /*----------------------------------------------------------------------------*/
4375 /*! \brief This routine is called to update a disconnection event.
4376 *
4377 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure
4378 * \param[in] pucPeerMac Pointer to the MAC of the TDLS peer
4379 * \param[in] eFmeStatus TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME
4380 * \param[in] pInfo other information
4381 *
4382 * \retval none
4383 */
4384 /*----------------------------------------------------------------------------*/
4385 static VOID
4386 TdlsLinkHistoryRecordUpdate(
4387 GLUE_INFO_T *prGlueInfo,
4388 UINT8 *pucPeerMac,
4389 TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus,
4390 VOID *pInfo
4391 )
4392 {
4393 TDLS_INFO_LINK_T *prLink;
4394 UINT32 u4LinkIdx;
4395 UINT32 u4Tid;
4396
4397
4398 /* sanity check */
4399 if ((eFmeStatus < TDLS_HOST_EVENT_SF_BA) ||
4400 (eFmeStatus > TDLS_HOST_EVENT_SF_BA_RSP_DECLINE))
4401 {
4402 /* do not care these frames */
4403 return;
4404 }
4405
4406 DBGLOG(TDLS, INFO,
4407 ("<tdls_evt> %s: update history for "MACSTR" %d %d\n",
4408 __FUNCTION__, MAC2STR(pucPeerMac), prGlueInfo->rTdlsLink.u4LinkIdx,
4409 eFmeStatus));
4410
4411 /* init */
4412 u4LinkIdx = prGlueInfo->rTdlsLink.u4LinkIdx;
4413 prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4LinkIdx];
4414
4415 /* TODO: need to search all entries to find it if we support multiple TDLS link design */
4416 if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0)
4417 {
4418 /* error! can not find the link entry */
4419 DBGLOG(TDLS, INFO,
4420 ("<tdls_evt> %s: cannot find the same entry!!!\n",
4421 __FUNCTION__));
4422 return;
4423 }
4424
4425 /* update */
4426 u4Tid = *(UINT32 *)pInfo;
4427 switch(eFmeStatus)
4428 {
4429 case TDLS_HOST_EVENT_SF_BA:
4430 prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP;
4431 break;
4432
4433 case TDLS_HOST_EVENT_SF_BA_OK:
4434 prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_OK;
4435 break;
4436
4437 case TDLS_HOST_EVENT_SF_BA_DECLINE:
4438 prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_DECLINE;
4439 break;
4440
4441 case TDLS_HOST_EVENT_SF_BA_PEER:
4442 prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_PEER;
4443 break;
4444
4445 case TDLS_HOST_EVENT_SF_BA_RSP_OK:
4446 prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_OK;
4447 break;
4448
4449 case TDLS_HOST_EVENT_SF_BA_RSP_DECLINE:
4450 prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_DECLINE;
4451 break;
4452 }
4453
4454 /* display TDLS link history */
4455 TdlsInfoDisplay(prGlueInfo->prAdapter, NULL, 0, NULL);
4456 }
4457
4458
4459 /*----------------------------------------------------------------------------*/
4460 /*! \brief This routine is called to configure TDLS MIB parameters.
4461 *
4462 * \param[in] prAdapter Pointer to the Adapter structure
4463 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
4464 * \param[in] u4SetBufferLen The length of the set buffer
4465 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
4466 * bytes read from the set buffer. If the call failed due to invalid length of
4467 * the set buffer, returns the amount of storage needed.
4468 *
4469 * \retval TDLS_STATUS_xx
4470 *
4471 */
4472 /*----------------------------------------------------------------------------*/
4473 static TDLS_STATUS
4474 TdlsMibParamUpdate(
4475 ADAPTER_T *prAdapter,
4476 VOID *pvSetBuffer,
4477 UINT_32 u4SetBufferLen,
4478 UINT_32 *pu4SetInfoLen
4479 )
4480 {
4481 TDLS_CMD_CORE_T *prCmdContent;
4482 WLAN_STATUS rStatus;
4483
4484
4485 /* init command buffer */
4486 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
4487 prCmdContent->u4Command = TDLS_CORE_CMD_MIB_UPDATE;
4488
4489 /* send the command */
4490 rStatus = wlanSendSetQueryCmd (
4491 prAdapter, /* prAdapter */
4492 CMD_ID_TDLS_CORE, /* ucCID */
4493 TRUE, /* fgSetQuery */
4494 FALSE, /* fgNeedResp */
4495 FALSE, /* fgIsOid */
4496 NULL,
4497 NULL, /* pfCmdTimeoutHandler */
4498 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
4499 (PUINT_8) prCmdContent, /* pucInfoBuffer */
4500 NULL, /* pvSetQueryBuffer */
4501 0 /* u4SetQueryBufferLen */
4502 );
4503
4504 if (rStatus != WLAN_STATUS_PENDING)
4505 {
4506 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
4507 __FUNCTION__));
4508 return TDLS_STATUS_RESOURCES;
4509 }
4510
4511 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
4512 return TDLS_STATUS_SUCCESS;
4513 }
4514
4515
4516 /*----------------------------------------------------------------------------*/
4517 /*! \brief This routine is called to configure TDLS SETUP parameters.
4518 *
4519 * \param[in] prAdapter Pointer to the Adapter structure
4520 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
4521 * \param[in] u4SetBufferLen The length of the set buffer
4522 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
4523 * bytes read from the set buffer. If the call failed due to invalid length of
4524 * the set buffer, returns the amount of storage needed.
4525 *
4526 * \retval TDLS_STATUS_xx
4527 *
4528 */
4529 /*----------------------------------------------------------------------------*/
4530 static TDLS_STATUS
4531 TdlsSetupConf(
4532 ADAPTER_T *prAdapter,
4533 VOID *pvSetBuffer,
4534 UINT_32 u4SetBufferLen,
4535 UINT_32 *pu4SetInfoLen
4536 )
4537 {
4538 TDLS_CMD_CORE_T *prCmdContent;
4539 WLAN_STATUS rStatus;
4540
4541
4542 /* init command buffer */
4543 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
4544 prCmdContent->u4Command = TDLS_CORE_CMD_SETUP_CONF;
4545
4546 /* send the command */
4547 rStatus = wlanSendSetQueryCmd (
4548 prAdapter, /* prAdapter */
4549 CMD_ID_TDLS_CORE, /* ucCID */
4550 TRUE, /* fgSetQuery */
4551 FALSE, /* fgNeedResp */
4552 FALSE, /* fgIsOid */
4553 NULL,
4554 NULL, /* pfCmdTimeoutHandler */
4555 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
4556 (PUINT_8) prCmdContent, /* pucInfoBuffer */
4557 NULL, /* pvSetQueryBuffer */
4558 0 /* u4SetQueryBufferLen */
4559 );
4560
4561 if (rStatus != WLAN_STATUS_PENDING)
4562 {
4563 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
4564 __FUNCTION__));
4565 return TDLS_STATUS_RESOURCES;
4566 }
4567
4568 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
4569 return TDLS_STATUS_SUCCESS;
4570 }
4571
4572
4573 /*----------------------------------------------------------------------------*/
4574 /*! \brief This routine is called to configure UAPSD parameters.
4575 *
4576 * \param[in] prAdapter Pointer to the Adapter structure
4577 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
4578 * \param[in] u4SetBufferLen The length of the set buffer
4579 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
4580 * bytes read from the set buffer. If the call failed due to invalid length of
4581 * the set buffer, returns the amount of storage needed.
4582 *
4583 * \retval TDLS_STATUS_xx
4584 *
4585 */
4586 /*----------------------------------------------------------------------------*/
4587 static TDLS_STATUS
4588 TdlsUapsdConf(
4589 ADAPTER_T *prAdapter,
4590 VOID *pvSetBuffer,
4591 UINT_32 u4SetBufferLen,
4592 UINT_32 *pu4SetInfoLen
4593 )
4594 {
4595 TDLS_CMD_CORE_T *prCmdContent;
4596 WLAN_STATUS rStatus;
4597
4598
4599 /* init command buffer */
4600 prCmdContent = (TDLS_CMD_CORE_T *)pvSetBuffer;
4601 prCmdContent->u4Command = TDLS_CORE_CMD_UAPSD_CONF;
4602
4603 /* send the command */
4604 rStatus = wlanSendSetQueryCmd (
4605 prAdapter, /* prAdapter */
4606 CMD_ID_TDLS_CORE, /* ucCID */
4607 TRUE, /* fgSetQuery */
4608 FALSE, /* fgNeedResp */
4609 FALSE, /* fgIsOid */
4610 NULL,
4611 NULL, /* pfCmdTimeoutHandler */
4612 sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */
4613 (PUINT_8) prCmdContent, /* pucInfoBuffer */
4614 NULL, /* pvSetQueryBuffer */
4615 0 /* u4SetQueryBufferLen */
4616 );
4617
4618 if (rStatus != WLAN_STATUS_PENDING)
4619 {
4620 DBGLOG(TDLS, ERROR, ("%s wlanSendSetQueryCmd allocation fail!\n",
4621 __FUNCTION__));
4622 return TDLS_STATUS_RESOURCES;
4623 }
4624
4625 DBGLOG(TDLS, INFO, ("%s cmd ok.\n", __FUNCTION__));
4626 return TDLS_STATUS_SUCCESS;
4627 }
4628
4629
4630 /*----------------------------------------------------------------------------*/
4631 /*! \brief This routine is called to update frame status.
4632 *
4633 * \param[in] prGlueInfo Pointer to the Adapter structure
4634 * \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId
4635 * \param[in] u4InBufLen The length of the buffer
4636 * \param[out] None
4637 *
4638 * \retval None
4639 *
4640 */
4641 /*----------------------------------------------------------------------------*/
4642 static void
4643 TdlsEventFmeStatus(
4644 GLUE_INFO_T *prGlueInfo,
4645 UINT8 *prInBuf,
4646 UINT32 u4InBufLen
4647 )
4648 {
4649 TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus;
4650 STA_RECORD_T *prStaRec;
4651 UINT32 u4Tid;
4652
4653
4654 /* init */
4655 u4Tid = *(UINT32 *)prInBuf;
4656 prInBuf += 4; /* skip u4EventSubId */
4657
4658 /* sanity check */
4659 prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf);
4660 if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec)))
4661 return;
4662 prInBuf ++;
4663
4664 /* update status */
4665 eFmeStatus = *prInBuf;
4666 TdlsLinkHistoryRecordUpdate(prGlueInfo, prStaRec->aucMacAddr,
4667 eFmeStatus, &u4Tid);
4668 }
4669
4670
4671 /*----------------------------------------------------------------------------*/
4672 /*! \brief This routine is called to collect TDLS statistics from firmware.
4673 *
4674 * \param[in] prGlueInfo Pointer to the Adapter structure
4675 * \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId
4676 * \param[in] u4InBufLen The length of the buffer
4677 * \param[out] None
4678 *
4679 * \retval None
4680 *
4681 */
4682 /*----------------------------------------------------------------------------*/
4683 static void
4684 TdlsEventStatistics(
4685 GLUE_INFO_T *prGlueInfo,
4686 UINT8 *prInBuf,
4687 UINT32 u4InBufLen
4688 )
4689 {
4690 STA_RECORD_T *prStaRec;
4691 STAT_CNT_INFO_FW_T *prStat;
4692 UINT32 u4RateId;
4693
4694
4695 /* init */
4696 prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf);
4697 if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec)))
4698 return;
4699
4700 prInBuf += 4; /* skip prStaRec->ucIndex */
4701
4702 /* update statistics */
4703 kalMemCopy(&prStaRec->rTdlsStatistics.rFw, prInBuf,\
4704 sizeof(prStaRec->rTdlsStatistics.rFw));
4705
4706 /* display statistics */
4707 prStat = &prStaRec->rTdlsStatistics.rFw;
4708
4709 DBGLOG(TDLS, TRACE, ("<tdls_evt> peer ["MACSTR"] statistics:\n",
4710 MAC2STR(prStaRec->aucMacAddr)));
4711 DBGLOG(TDLS, TRACE, ("\t\tT%d %d %d (P%d %d) (%dus) - E%d 0x%x - R%d (P%d)\n",
4712 prStat->u4NumOfTx, prStat->u4NumOfTxOK, prStat->u4NumOfTxRetry,
4713 prStat->u4NumOfPtiRspTxOk, prStat->u4NumOfPtiRspTxErr,
4714 prStat->u4TxDoneAirTimeMax,
4715 prStat->u4NumOfTxErr, prStat->u4TxErrBitmap,
4716 prStat->u4NumOfRx, prStat->u4NumOfPtiRspRx));
4717
4718 DBGLOG(TDLS, TRACE, ("\t\t"));
4719
4720 for(u4RateId=prStat->u4TxRateOkHisId;
4721 u4RateId<STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM;
4722 u4RateId++)
4723 {
4724 printk("%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0],
4725 prStat->aucTxRateOkHis[u4RateId][1]);
4726 }
4727 for(u4RateId=0;
4728 u4RateId<prStat->u4TxRateOkHisId;
4729 u4RateId++)
4730 {
4731 printk("%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0],
4732 prStat->aucTxRateOkHis[u4RateId][1]);
4733 }
4734
4735 printk("\n");
4736
4737 printk("\n");
4738 }
4739
4740
4741 /*----------------------------------------------------------------------------*/
4742 /*! \brief This routine is called to do tear down.
4743 *
4744 * \param[in] prGlueInfo Pointer to the Adapter structure
4745 * \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId
4746 * \param[in] u4InBufLen The length of the buffer
4747 * \param[out] None
4748 *
4749 * \retval None
4750 *
4751 */
4752 /*----------------------------------------------------------------------------*/
4753 static void
4754 TdlsEventTearDown(
4755 GLUE_INFO_T *prGlueInfo,
4756 UINT8 *prInBuf,
4757 UINT32 u4InBufLen
4758 )
4759 {
4760 STA_RECORD_T *prStaRec;
4761 UINT16 u2ReasonCode;
4762 UINT32 u4TearDownSubId;
4763 UINT8 *pMac, aucZeroMac[6];
4764
4765
4766 /* init */
4767 u4TearDownSubId = *(UINT32 *)prInBuf;
4768 kalMemZero(aucZeroMac, sizeof(aucZeroMac));
4769 pMac = aucZeroMac;
4770
4771 prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *(prInBuf+4));
4772 if (prStaRec != NULL)
4773 pMac = prStaRec->aucMacAddr;
4774
4775 /* handle */
4776 if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT)
4777 {
4778 DBGLOG(TDLS, WARN, ("<tdls_evt> %s: peer ["MACSTR"] Reason=PTI timeout\n",
4779 __FUNCTION__, MAC2STR(pMac)));
4780 }
4781 else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT)
4782 {
4783 DBGLOG(TDLS, WARN, ("<tdls_evt> %s: peer ["MACSTR"] Reason=AGE timeout\n",
4784 __FUNCTION__, MAC2STR(pMac)));
4785 }
4786 else
4787 {
4788 DBGLOG(TDLS, WARN, ("<tdls_evt> %s: peer ["MACSTR"] Reason=%d\n",
4789 __FUNCTION__, MAC2STR(pMac), u4TearDownSubId));
4790 }
4791
4792 /* sanity check */
4793 if (prStaRec == NULL)
4794 return;
4795
4796 if (fgIsPtiTimeoutSkip == TRUE)
4797 {
4798 /* skip PTI timeout event */
4799 if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT)
4800 {
4801 DBGLOG(TDLS, WARN, ("<tdls_evt> %s: skip PTI timeout\n",
4802 __FUNCTION__));
4803 return;
4804 }
4805 }
4806
4807 /* record history */
4808 if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT)
4809 u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT;
4810 else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT)
4811 u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT;
4812 else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_FAIL)
4813 u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL;
4814 else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL)
4815 u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL;
4816 else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX)
4817 u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX;
4818 else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_NON_STATE3)
4819 u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3;
4820 else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN)
4821 u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN;
4822 else
4823 {
4824 /* shall not be here */
4825 u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN;
4826 }
4827
4828 TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr, TRUE,
4829 u2ReasonCode, NULL);
4830
4831 /* correct correct reason code for PTI or AGE timeout to supplicant */
4832 if ((u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT) ||
4833 (u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT))
4834 {
4835 u2ReasonCode = TDLS_REASON_CODE_UNREACHABLE;
4836 }
4837
4838 /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */
4839 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
4840 cfg80211_tdls_oper_request(prGlueInfo->prDevHandler,
4841 prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN, u2ReasonCode, GFP_ATOMIC);
4842 #else
4843 cfg80211_tdls_oper_request(prGlueInfo->prDevHandler,
4844 prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, u2ReasonCode, GFP_ATOMIC);
4845 #endif
4846 }
4847
4848
4849 /*----------------------------------------------------------------------------*/
4850 /*! \brief This routine is called to do tx down.
4851 *
4852 * \param[in] prGlueInfo Pointer to the Adapter structure
4853 * \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId
4854 * \param[in] u4InBufLen The length of the buffer
4855 * \param[out] None
4856 *
4857 * \retval None
4858 *
4859 */
4860 /*----------------------------------------------------------------------------*/
4861 static void
4862 TdlsEventTxDone(
4863 GLUE_INFO_T *prGlueInfo,
4864 UINT8 *prInBuf,
4865 UINT32 u4InBufLen
4866 )
4867 {
4868 UINT32 u4FmeIdx;
4869 UINT8 *pucFmeHdr;
4870 UINT8 ucErrStatus;
4871
4872
4873 ucErrStatus = *(UINT32 *)prInBuf;
4874
4875 pucFmeHdr = prInBuf+4; /* skip ucErrStatus */
4876
4877 if (ucErrStatus == 0)
4878 {
4879 DBGLOG(TDLS, TRACE,
4880 ("<tdls_evt> %s: OK to tx a TDLS action:",
4881 __FUNCTION__));
4882 }
4883 else
4884 {
4885 DBGLOG(TDLS, TRACE,
4886 ("<tdls_evt> %s: fail to tx a TDLS action (err=0x%x):",
4887 __FUNCTION__, ucErrStatus));
4888 }
4889
4890 /* dump TX packet content from wlan header */
4891 for(u4FmeIdx=0; u4FmeIdx<(u4InBufLen-4); u4FmeIdx++)
4892 {
4893 if ((u4FmeIdx % 16) == 0)
4894 {
4895 printk("\n");
4896 }
4897
4898 printk("%02x ", *pucFmeHdr++);
4899 }
4900
4901 printk("\n\n");
4902 }
4903
4904
4905 /*******************************************************************************
4906 * P U B L I C F U N C T I O N S
4907 ********************************************************************************
4908 */
4909
4910 /*----------------------------------------------------------------------------*/
4911 /*! \brief This routine is called to parse TDLS Extended Capabilities element.
4912 *
4913 * \param[in] prGlueInfo Pointer to the Adapter structure
4914 * \param[in] prInBuf A pointer to the command string buffer
4915 * \param[in] u4InBufLen The length of the buffer
4916 * \param[out] None
4917 *
4918 * \retval None
4919 */
4920 /*----------------------------------------------------------------------------*/
4921 VOID
4922 TdlsexBssExtCapParse(
4923 STA_RECORD_T *prStaRec,
4924 UINT_8 *pucIE
4925 )
4926 {
4927 UINT_8 *pucIeExtCap;
4928
4929
4930 /* sanity check */
4931 if ((prStaRec == NULL) || (pucIE == NULL))
4932 return;
4933
4934 if (IE_ID(pucIE) != ELEM_ID_EXTENDED_CAP)
4935 return;
4936
4937 /*
4938 from bit0 ~
4939
4940 bit 38: TDLS Prohibited
4941 The TDLS Prohibited subfield indicates whether the use of TDLS is prohibited. The
4942 field is set to 1 to indicate that TDLS is prohibited and to 0 to indicate that TDLS is
4943 allowed.
4944 */
4945 if (IE_LEN(pucIE) < 5)
4946 return; /* we need 39/8 = 5 bytes */
4947
4948 /* init */
4949 prStaRec->fgTdlsIsProhibited = FALSE;
4950 prStaRec->fgTdlsIsChSwProhibited = FALSE;
4951
4952 /* parse */
4953 pucIeExtCap = pucIE + 2;
4954 pucIeExtCap += 4; /* shift to the byte we care about */
4955
4956 if ((*pucIeExtCap) && BIT(38-32))
4957 prStaRec->fgTdlsIsProhibited = TRUE;
4958 if ((*pucIeExtCap) && BIT(39-32))
4959 prStaRec->fgTdlsIsChSwProhibited = TRUE;
4960
4961 DBGLOG(TDLS, TRACE,
4962 ("<tdls> %s: AP ["MACSTR"] tdls prohibit bit=%d %d\n",
4963 __FUNCTION__,
4964 MAC2STR(prStaRec->aucMacAddr),
4965 prStaRec->fgTdlsIsProhibited,
4966 prStaRec->fgTdlsIsChSwProhibited));
4967 }
4968
4969
4970 /*----------------------------------------------------------------------------*/
4971 /*!
4972 * \brief This routine is called to transmit a TDLS data frame from nl80211.
4973 *
4974 * \param[in] pvAdapter Pointer to the Adapter structure.
4975 * \param[in]
4976 * \param[in]
4977 * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE
4978 *
4979 * \retval WLAN_STATUS_SUCCESS
4980 * \retval WLAN_STATUS_INVALID_LENGTH
4981 */
4982 /*----------------------------------------------------------------------------*/
4983 int
4984 TdlsexCfg80211TdlsMgmt(
4985 struct wiphy *wiphy,
4986 struct net_device *dev,
4987 u8 *peer,
4988 u8 action_code,
4989 u8 dialog_token,
4990 u16 status_code,
4991 const u8 *buf,
4992 size_t len
4993 )
4994 {
4995 ADAPTER_T *prAdapter;
4996 GLUE_INFO_T *prGlueInfo;
4997 BSS_INFO_T *prAisBssInfo;
4998 WLAN_STATUS rStatus;
4999 UINT_32 u4BufLen;
5000 TDLS_MGMT_TX_INFO *prMgmtTxInfo;
5001
5002
5003 /*
5004 Have correct behavior for STAUT receiving TDLS Setup Request after sending TDLS
5005 Set Request and before receiving TDLS Setup Response:
5006 -- Source Address of received Request is higher than own MAC address
5007 -- Source Address of received Request is lower than own MAC address
5008
5009 ==> STA with larger MAC address will send the response frame.
5010
5011 Supplicant will do this in wpa_tdls_process_tpk_m1().
5012 */
5013
5014 /* sanity check */
5015 if ((wiphy == NULL) || (peer == NULL))
5016 {
5017 DBGLOG(TDLS, ERROR,
5018 ("<tdls_cfg> %s: wrong 0x%p 0x%p!\n",
5019 __FUNCTION__, wiphy, peer));
5020 return -EINVAL;
5021 }
5022
5023 DBGLOG(TDLS, INFO, ("<tdls_cfg> %s: ["MACSTR"] %d %d %d 0x%p %u\n",
5024 __FUNCTION__, MAC2STR(peer),
5025 action_code, dialog_token, status_code, buf, (UINT32)len));
5026
5027 /* init */
5028 prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy);
5029 if (prGlueInfo == NULL)
5030 {
5031 DBGLOG(TDLS, ERROR,
5032 ("<tdls_cfg> %s: wrong prGlueInfo 0x%p!\n",
5033 __FUNCTION__, prGlueInfo));
5034 return -EINVAL;
5035 }
5036
5037 prAdapter = prGlueInfo->prAdapter;
5038 if (prAdapter->fgTdlsIsSup == FALSE)
5039 {
5040 DBGLOG(TDLS, ERROR,
5041 ("<tdls_cfg> %s: firmware TDLS is not supported!\n",
5042 __FUNCTION__));
5043 return -EBUSY;
5044 }
5045
5046 prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
5047 if (prAisBssInfo->fgTdlsIsProhibited == TRUE)
5048 {
5049 /* do not send anything if TDLS is prohibited in the BSS */
5050 return 0;
5051 }
5052
5053 prMgmtTxInfo = kalMemAlloc(sizeof(TDLS_MGMT_TX_INFO), VIR_MEM_TYPE);
5054 if (prMgmtTxInfo == NULL)
5055 {
5056 DBGLOG(TDLS, ERROR,
5057 ("<tdls_cfg> %s: allocate fail!\n",
5058 __FUNCTION__));
5059 return -ENOMEM;
5060 }
5061
5062 kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO));
5063
5064 if (peer != NULL)
5065 kalMemCopy(prMgmtTxInfo->aucPeer, peer, 6);
5066 prMgmtTxInfo->ucActionCode = action_code;
5067 prMgmtTxInfo->ucDialogToken = dialog_token;
5068 prMgmtTxInfo->u2StatusCode = status_code;
5069
5070 if (buf != NULL)
5071 {
5072 if (len > sizeof(prMgmtTxInfo->aucSecBuf))
5073 {
5074 kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO));
5075 return -EINVAL;
5076 }
5077 prMgmtTxInfo->u4SecBufLen = len;
5078 kalMemCopy(prMgmtTxInfo->aucSecBuf, buf, len);
5079 }
5080
5081 /* send the TDLS action data frame */
5082 rStatus = kalIoctl(prGlueInfo,
5083 TdlsexMgmtCtrl,
5084 prMgmtTxInfo,
5085 sizeof(TDLS_MGMT_TX_INFO),
5086 FALSE,
5087 FALSE,
5088 FALSE,
5089 FALSE,
5090 &u4BufLen);
5091
5092 /*
5093 clear all content to avoid any bug if we dont yet execute TdlsexMgmtCtrl()
5094 then kalIoctl finishes
5095 */
5096 kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO));
5097
5098 if (rStatus != WLAN_STATUS_SUCCESS)
5099 {
5100 DBGLOG(TDLS, ERROR,
5101 ("%s enable or disable link fail:%x\n", __FUNCTION__, rStatus));
5102 kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO));
5103 return -EINVAL;
5104 }
5105
5106 kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO));
5107 return 0;
5108 }
5109
5110
5111 /*----------------------------------------------------------------------------*/
5112 /*!
5113 * \brief This routine is called to enable or disable TDLS link from upper layer.
5114 *
5115 * \param[in] pvAdapter Pointer to the Adapter structure.
5116 * \param[in]
5117 * \param[in]
5118 * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE
5119 *
5120 * \retval WLAN_STATUS_SUCCESS
5121 * \retval WLAN_STATUS_INVALID_LENGTH
5122 */
5123 /*----------------------------------------------------------------------------*/
5124 int
5125 TdlsexCfg80211TdlsOper(
5126 struct wiphy *wiphy,
5127 struct net_device *dev,
5128 u8 *peer,
5129 enum nl80211_tdls_operation oper
5130 )
5131 {
5132 ADAPTER_T *prAdapter;
5133 GLUE_INFO_T *prGlueInfo;
5134 WLAN_STATUS rStatus;
5135 UINT_32 u4BufLen;
5136 TDLS_CMD_LINK_T rCmdLink;
5137
5138
5139 /* sanity check */
5140 if (peer == NULL)
5141 {
5142 DBGLOG(TDLS, ERROR, ("<tdls_cfg> %s: peer == NULL!\n", __FUNCTION__));
5143 return -EINVAL;
5144 }
5145
5146 DBGLOG(TDLS, INFO, ("<tdls_cfg> %s: ["MACSTR"] %d %d\n",
5147 __FUNCTION__, MAC2STR(peer), oper,
5148 (wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)));
5149
5150 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
5151 return -ENOTSUPP;
5152
5153 /* init */
5154 prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy);
5155 if (prGlueInfo == NULL)
5156 {
5157 DBGLOG(TDLS, ERROR,
5158 ("<tdls_cfg> %s: wrong prGlueInfo 0x%p!\n",
5159 __FUNCTION__, prGlueInfo));
5160 return -EINVAL;
5161 }
5162 prAdapter = prGlueInfo->prAdapter;
5163 kalMemCopy(rCmdLink.aucPeerMac, peer, sizeof(rCmdLink.aucPeerMac));
5164 rCmdLink.fgIsEnabled = FALSE;
5165
5166 /*
5167 enum nl80211_tdls_operation {
5168 NL80211_TDLS_DISCOVERY_REQ,
5169 NL80211_TDLS_SETUP,
5170 NL80211_TDLS_TEARDOWN,
5171 NL80211_TDLS_ENABLE_LINK,
5172 NL80211_TDLS_DISABLE_LINK,
5173 };
5174 */
5175
5176 switch(oper)
5177 {
5178 case NL80211_TDLS_ENABLE_LINK:
5179 rCmdLink.fgIsEnabled = TRUE;
5180 break;
5181
5182 case NL80211_TDLS_DISABLE_LINK:
5183 rCmdLink.fgIsEnabled = FALSE;
5184 break;
5185
5186 case NL80211_TDLS_TEARDOWN:
5187 case NL80211_TDLS_SETUP:
5188 case NL80211_TDLS_DISCOVERY_REQ:
5189 /* we do not support setup/teardown/discovery from driver */
5190 return -ENOTSUPP;
5191
5192 default:
5193 return -ENOTSUPP;
5194 }
5195
5196 /* enable or disable TDLS link */
5197 rStatus = kalIoctl(prGlueInfo,
5198 TdlsexLinkCtrl,
5199 &rCmdLink,
5200 sizeof(TDLS_CMD_LINK_T),
5201 FALSE,
5202 FALSE,
5203 FALSE,
5204 FALSE,
5205 &u4BufLen);
5206
5207 if (rStatus != WLAN_STATUS_SUCCESS)
5208 {
5209 DBGLOG(TDLS, ERROR,
5210 ("%s enable or disable link fail:%x\n", __FUNCTION__, rStatus));
5211 return -EINVAL;
5212 }
5213
5214 return 0;
5215 }
5216
5217
5218 /*----------------------------------------------------------------------------*/
5219 /*! \brief This routine is called to send a command to TDLS module.
5220 *
5221 * \param[in] prGlueInfo Pointer to the Adapter structure
5222 * \param[in] prInBuf A pointer to the command string buffer
5223 * \param[in] u4InBufLen The length of the buffer
5224 * \param[out] None
5225 *
5226 * \retval None
5227 */
5228 /*----------------------------------------------------------------------------*/
5229 VOID
5230 TdlsexCmd(
5231 P_GLUE_INFO_T prGlueInfo,
5232 UINT_8 *prInBuf,
5233 UINT_32 u4InBufLen
5234 )
5235 {
5236 UINT_32 u4Subcmd;
5237
5238
5239 /* parse TDLS sub-command */
5240 u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen);
5241 DBGLOG(TDLS, INFO, ("<tdls_cmd> sub command = %u\n", (UINT32)u4Subcmd));
5242
5243 /* handle different sub-command */
5244 switch(u4Subcmd)
5245 {
5246 #if TDLS_CFG_CMD_TEST /* only for unit test */
5247 case TDLS_CMD_TEST_TX_FRAME:
5248 /* simulate to send a TDLS frame */
5249 TdlsCmdTestTxFrame(prGlueInfo, prInBuf, u4InBufLen);
5250 break;
5251
5252 case TDLS_CMD_TEST_TX_TDLS_FRAME:
5253 /* simulate to send a TDLS frame from supplicant */
5254 TdlsCmdTestTxTdlsFrame(prGlueInfo, prInBuf, u4InBufLen);
5255 break;
5256
5257 case TDLS_CMD_TEST_RCV_FRAME:
5258 /* simulate to receive a TDLS frame */
5259 TdlsCmdTestRvFrame(prGlueInfo, prInBuf, u4InBufLen);
5260 break;
5261
5262 case TDLS_CMD_TEST_PEER_ADD:
5263 /* simulate to add a TDLS peer */
5264 TdlsCmdTestAddPeer(prGlueInfo, prInBuf, u4InBufLen);
5265 break;
5266
5267 case TDLS_CMD_TEST_PEER_UPDATE:
5268 /* simulate to update a TDLS peer */
5269 TdlsCmdTestUpdatePeer(prGlueInfo, prInBuf, u4InBufLen);
5270 break;
5271
5272 case TDLS_CMD_TEST_DATA_FRAME:
5273 /* simulate to send a data frame to the peer */
5274 TdlsCmdTestDataSend(prGlueInfo, prInBuf, u4InBufLen);
5275 break;
5276
5277 case TDLS_CMD_TEST_RCV_NULL:
5278 /* simulate to receive a QoS null frame from the peer */
5279 TdlsCmdTestNullRecv(prGlueInfo, prInBuf, u4InBufLen);
5280 break;
5281
5282 case TDLS_CMD_TEST_SKIP_TX_FAIL:
5283 /* command firmware to skip tx fail case */
5284 TdlsCmdTestTxFailSkip(prGlueInfo, prInBuf, u4InBufLen);
5285 break;
5286
5287 case TDLS_CMD_TEST_SKIP_KEEP_ALIVE:
5288 /* command firmware to skip keep alive function */
5289 TdlsCmdTestKeepAliveSkip(prGlueInfo, prInBuf, u4InBufLen);
5290 break;
5291
5292 case TDLS_CMD_TEST_SKIP_CHSW_TIMEOUT:
5293 /* command firmware to skip channel switch timeout function */
5294 TdlsCmdTestChSwTimeoutSkip(prGlueInfo, prInBuf, u4InBufLen);
5295 break;
5296
5297 case TDLS_CMD_TEST_PROHIBIT_SET_IN_AP:
5298 /* simulate to set Prohibited Bit in AP */
5299 TdlsCmdTestProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen);
5300 break;
5301
5302 case TDLS_CMD_TEST_SCAN_DISABLE:
5303 /* command to disable scan request to do channel switch */
5304 TdlsCmdTestScanCtrl(prGlueInfo, prInBuf, u4InBufLen);
5305 break;
5306
5307 case TDLS_CMD_TEST_DATA_FRAME_CONT:
5308 /* simulate to send a data frame to the peer periodically */
5309 TdlsCmdTestDataContSend(prGlueInfo, prInBuf, u4InBufLen);
5310 break;
5311
5312 case TDLS_CMD_TEST_CH_SW_PROHIBIT_SET_IN_AP:
5313 /* simulate to set channel switch Prohibited Bit in AP */
5314 TdlsCmdTestChSwProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen);
5315 break;
5316
5317 case TDLS_CMD_TEST_DELAY:
5318 /* delay a where */
5319 TdlsCmdTestDelay(prGlueInfo, prInBuf, u4InBufLen);
5320 break;
5321
5322 case TDLS_CMD_TEST_PTI_TX_FAIL:
5323 /* simulate the tx done fail for PTI */
5324 TdlsCmdTestPtiTxDoneFail(prGlueInfo, prInBuf, u4InBufLen);
5325 break;
5326 #endif /* TDLS_CFG_CMD_TEST */
5327
5328 case TDLS_CMD_MIB_UPDATE:
5329 /* update MIB parameters */
5330 TdlsCmdMibParamUpdate(prGlueInfo, prInBuf, u4InBufLen);
5331 break;
5332
5333 case TDLS_CMD_UAPSD_CONF:
5334 /* config UAPSD parameters */
5335 TdlsCmdUapsdConf(prGlueInfo, prInBuf, u4InBufLen);
5336 break;
5337
5338 case TDLS_CMD_CH_SW_CONF:
5339 /* enable or disable or start or stop channel switch function */
5340 TdlsCmdChSwConf(prGlueInfo, prInBuf, u4InBufLen);
5341 break;
5342
5343 case TDLS_CMD_SETUP_CONF:
5344 /* config setup parameters */
5345 TdlsCmdSetupConf(prGlueInfo, prInBuf, u4InBufLen);
5346 break;
5347
5348 case TDLS_CMD_INFO:
5349 /* display all TDLS information */
5350 TdlsCmdInfoDisplay(prGlueInfo, prInBuf, u4InBufLen);
5351 break;
5352
5353 case TDLS_CMD_KEY_INFO:
5354 /* display key information */
5355 TdlsCmdKeyInfoDisplay(prGlueInfo, prInBuf, u4InBufLen);
5356 break;
5357
5358 default:
5359 break;
5360 }
5361 }
5362
5363
5364 /*----------------------------------------------------------------------------*/
5365 /*! \brief This routine is called to record a disconnection event.
5366 *
5367 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure
5368 * \param[in] fgIsTearDown TRUE: tear down
5369 * \param[in] pucPeerMac Pointer to the MAC of the TDLS peer
5370 * \param[in] fgIsFromUs TRUE: tear down is from us
5371 * \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE)
5372 *
5373 * \retval none
5374 *
5375 */
5376 /*----------------------------------------------------------------------------*/
5377 VOID
5378 TdlsexLinkHistoryRecord(
5379 GLUE_INFO_T *prGlueInfo,
5380 BOOLEAN fgIsTearDown,
5381 UINT8 *pucPeerMac,
5382 BOOLEAN fgIsFromUs,
5383 UINT16 u2ReasonCode
5384 )
5385 {
5386 /* sanity check */
5387 if ((prGlueInfo == NULL) || (pucPeerMac == NULL))
5388 return;
5389
5390 DBGLOG(TDLS, INFO,
5391 ("<tdls_evt> %s: Rcv a inform from "MACSTR" %d %d\n",
5392 __FUNCTION__, MAC2STR(pucPeerMac), fgIsFromUs, u2ReasonCode));
5393
5394 /* record */
5395 TdlsLinkHistoryRecord(prGlueInfo, fgIsTearDown, pucPeerMac,\
5396 fgIsFromUs, u2ReasonCode, NULL);
5397 }
5398
5399
5400 /*----------------------------------------------------------------------------*/
5401 /*! \brief This routine is called to send a command to TDLS module.
5402 *
5403 * \param[in] prGlueInfo Pointer to the Adapter structure
5404 * \param[in] prInBuf A pointer to the command string buffer
5405 * \param[in] u4InBufLen The length of the buffer
5406 * \param[out] None
5407 *
5408 * \retval None
5409 */
5410 /*----------------------------------------------------------------------------*/
5411 VOID
5412 TdlsexEventHandle(
5413 GLUE_INFO_T *prGlueInfo,
5414 UINT8 *prInBuf,
5415 UINT32 u4InBufLen
5416 )
5417 {
5418 UINT32 u4EventId;
5419
5420
5421 /* sanity check */
5422 if ((prGlueInfo == NULL) || (prInBuf == NULL))
5423 return; /* shall not be here */
5424
5425 /* handle */
5426 u4EventId = *(UINT32 *)prInBuf;
5427 u4InBufLen -= 4;
5428
5429 DBGLOG(TDLS, INFO,
5430 ("<tdls> %s: Rcv a event: %d\n", __FUNCTION__, u4EventId));
5431
5432 switch(u4EventId)
5433 {
5434 case TDLS_HOST_EVENT_TEAR_DOWN:
5435 TdlsEventTearDown(prGlueInfo, prInBuf+4, u4InBufLen);
5436 break;
5437
5438 case TDLS_HOST_EVENT_TX_DONE:
5439 TdlsEventTxDone(prGlueInfo, prInBuf+4, u4InBufLen);
5440 break;
5441
5442 case TDLS_HOST_EVENT_FME_STATUS:
5443 TdlsEventFmeStatus(prGlueInfo, prInBuf+4, u4InBufLen);
5444 break;
5445
5446 case TDLS_HOST_EVENT_STATISTICS:
5447 TdlsEventStatistics(prGlueInfo, prInBuf+4, u4InBufLen);
5448 break;
5449 }
5450 }
5451
5452
5453 /*----------------------------------------------------------------------------*/
5454 /*!
5455 * @brief This function is used to initialize variables in TDLS.
5456 *
5457 * \param[in] prAdapter Pointer to the Adapter structure
5458 *
5459 * @return TDLS_STATUS_SUCCESS: do not set key and key infor. is queued
5460 TDLS_STATUS_FAILURE: set key
5461 */
5462 /*----------------------------------------------------------------------------*/
5463 TDLS_STATUS
5464 TdlsexKeyHandle(
5465 ADAPTER_T *prAdapter,
5466 PARAM_KEY_T *prNewKey
5467 )
5468 {
5469 STA_RECORD_T *prStaRec;
5470
5471
5472 /* sanity check */
5473 if ((prAdapter == NULL) || (prNewKey == NULL))
5474 return TDLS_STATUS_FAILURE;
5475
5476 /*
5477 supplicant will set key before updating station & enabling the link so we need to
5478 backup the key information and set key when link is enabled
5479 */
5480 prStaRec = cnmGetStaRecByAddress(\
5481 prAdapter, NETWORK_TYPE_AIS_INDEX, prNewKey->arBSSID);
5482 if ((prStaRec != NULL) && IS_TDLS_STA(prStaRec))
5483 {
5484 DBGLOG(TDLS, TRACE, ("<tdls> %s: ["MACSTR"] queue key (len=%d) "
5485 "until link is enabled\n",
5486 __FUNCTION__, MAC2STR(prNewKey->arBSSID),
5487 (UINT32)prNewKey->u4KeyLength));
5488
5489 if (prStaRec->ucStaState == STA_STATE_3)
5490 {
5491 DBGLOG(TDLS, TRACE, ("<tdls> %s: ["MACSTR"] tear down the link "
5492 "due to STA_STATE_3\n",
5493 __FUNCTION__, MAC2STR(prNewKey->arBSSID)));
5494
5495 /* re-key */
5496 TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE,
5497 prStaRec->aucMacAddr, TRUE,
5498 TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL);
5499
5500 /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */
5501 cfg80211_tdls_oper_request(prAdapter->prGlueInfo->prDevHandler,
5502 prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN,
5503 TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC);
5504 return TDLS_STATUS_SUCCESS;
5505 }
5506
5507 /* backup the key */
5508 kalMemCopy(&prStaRec->rTdlsKeyTemp, prNewKey, sizeof(prStaRec->rTdlsKeyTemp));
5509 return TDLS_STATUS_SUCCESS;
5510 }
5511
5512 return TDLS_STATUS_FAILURE;
5513 }
5514
5515
5516 /*----------------------------------------------------------------------------*/
5517 /*!
5518 * @brief This function is used to initialize variables in TDLS.
5519 *
5520 * \param[in] prAdapter Pointer to the Adapter structure
5521 *
5522 * @return (none)
5523 */
5524 /*----------------------------------------------------------------------------*/
5525 VOID
5526 TdlsexInit (
5527 ADAPTER_T *prAdapter
5528 )
5529 {
5530 GLUE_INFO_T *prGlueInfo;
5531
5532
5533 /* init */
5534 prGlueInfo = (GLUE_INFO_T *)prAdapter->prGlueInfo;
5535
5536 /* reset */
5537 kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink));
5538 }
5539
5540
5541 /*----------------------------------------------------------------------------*/
5542 /*!
5543 * \brief This routine is called to get any peer is in power save.
5544 *
5545 * \param[in] prAdapter Pointer to the Adapter structure
5546 *
5547 * \retval TRUE (at least one peer is in power save)
5548 */
5549 /*----------------------------------------------------------------------------*/
5550 BOOLEAN
5551 TdlsexIsAnyPeerInPowerSave(
5552 ADAPTER_T *prAdapter
5553 )
5554 {
5555 STA_RECORD_T *prStaRec;
5556 UINT32 u4StaId, u4StartIdx;
5557
5558
5559 for(u4StaId=0, u4StartIdx=0; u4StaId<CFG_STA_REC_NUM; u4StaId++)
5560 {
5561 /* list all TDLS peers */
5562 prStaRec = cnmStaTheTypeGet(prAdapter, NETWORK_TYPE_AIS_INDEX,
5563 STA_TYPE_TDLS_PEER, &u4StartIdx);
5564 if (prStaRec == NULL)
5565 break;
5566
5567 if (prStaRec->fgIsInPS == TRUE)
5568 {
5569 printk("<tx> yes, at least one peer is in ps\n");
5570 return TRUE;
5571 }
5572 }
5573
5574 return FALSE;
5575 }
5576
5577
5578 /*----------------------------------------------------------------------------*/
5579 /*!
5580 * \brief This routine is called to enable or disable a TDLS link.
5581 *
5582 * \param[in] prAdapter Pointer to the Adapter structure
5583 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
5584 * \param[in] u4SetBufferLen The length of the set buffer
5585 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
5586 * bytes read from the set buffer. If the call failed due to invalid length of
5587 * the set buffer, returns the amount of storage needed.
5588 *
5589 * \retval TDLS_STATUS_xx
5590 */
5591 /*----------------------------------------------------------------------------*/
5592 TDLS_STATUS
5593 TdlsexLinkCtrl (
5594 ADAPTER_T *prAdapter,
5595 VOID *pvSetBuffer,
5596 UINT_32 u4SetBufferLen,
5597 UINT_32 *pu4SetInfoLen
5598 )
5599 {
5600 GLUE_INFO_T *prGlueInfo;
5601 TDLS_CMD_LINK_T *prCmd;
5602 BSS_INFO_T *prBssInfo;
5603 STA_RECORD_T *prStaRec;
5604 TDLS_LINK_HIS_OTHERS_T rHisOthers;
5605
5606
5607 /* sanity check */
5608 if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL))
5609 {
5610 DBGLOG(TDLS, ERROR,
5611 ("<tdls_cmd> %s: sanity fail!\n", __FUNCTION__));
5612 return TDLS_STATUS_FAILURE;
5613 }
5614
5615 /* init */
5616 prGlueInfo = (GLUE_INFO_T *)prAdapter->prGlueInfo;
5617 *pu4SetInfoLen = sizeof(TDLS_CMD_LINK_T);
5618 prCmd = (TDLS_CMD_LINK_T *)pvSetBuffer;
5619
5620 /* search old entry */
5621 prStaRec = cnmGetStaRecByAddress(prAdapter,
5622 (UINT_8) NETWORK_TYPE_AIS_INDEX,
5623 prCmd->aucPeerMac);
5624 if (prStaRec == NULL)
5625 {
5626 DBGLOG(TDLS, ERROR, ("<tdls_cfg> %s: cannot find the peer! "MACSTR"\n",
5627 __FUNCTION__, MAC2STR(prCmd->aucPeerMac)));
5628 return TDLS_STATUS_FAILURE;
5629 }
5630
5631 if (prCmd->fgIsEnabled == TRUE)
5632 {
5633 cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3);
5634 DBGLOG(TDLS, TRACE, ("<tdls_cfg> %s: NL80211_TDLS_ENABLE_LINK\n",
5635 __FUNCTION__));
5636
5637 /* update key information after cnmStaRecChangeState(STA_STATE_3) */
5638 prStaRec->fgTdlsInSecurityMode = FALSE;
5639
5640 if (prStaRec->rTdlsKeyTemp.u4Length > 0)
5641 {
5642 UINT_32 u4BufLen; /* no use */
5643
5644 DBGLOG(TDLS, INFO, ("<tdls_cfg> %s: key len=%d\n",
5645 __FUNCTION__, (UINT32)prStaRec->rTdlsKeyTemp.u4Length));
5646
5647 /*
5648 reminder the function that we are CIPHER_SUITE_CCMP,
5649 do not change cipher type to CIPHER_SUITE_WEP128
5650 */
5651 _wlanoidSetAddKey(prAdapter, &prStaRec->rTdlsKeyTemp,
5652 prStaRec->rTdlsKeyTemp.u4Length, FALSE, CIPHER_SUITE_CCMP,
5653 &u4BufLen);
5654
5655 /* clear the temp key */
5656 prStaRec->fgTdlsInSecurityMode = TRUE;
5657 kalMemZero(&prStaRec->rTdlsKeyTemp, sizeof(prStaRec->rTdlsKeyTemp));
5658 }
5659
5660 /* check if we need to disable channel switch function */
5661 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
5662 if (prBssInfo->fgTdlsIsChSwProhibited == TRUE)
5663 {
5664 TDLS_CMD_CORE_T rCmd;
5665 kalMemZero(&rCmd, sizeof(TDLS_CMD_CORE_T));
5666 rCmd.Content.rCmdChSwConf.ucNetTypeIndex = prStaRec->ucNetTypeIndex;
5667 rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = FALSE;
5668 kalMemCopy(rCmd.aucPeerMac, prStaRec->aucMacAddr, 6);
5669 TdlsChSwConf(prAdapter, &rCmd, 0, 0);
5670
5671 DBGLOG(TDLS, INFO, ("<tdls_cfg> %s: disable channel switch\n",
5672 __FUNCTION__));
5673 }
5674
5675 TDLS_LINK_INCREASE(prGlueInfo);
5676
5677 /* record link */
5678 if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N)
5679 rHisOthers.fgIsHt = TRUE;
5680 else
5681 rHisOthers.fgIsHt = FALSE;
5682
5683 TdlsLinkHistoryRecord(prAdapter->prGlueInfo, FALSE,
5684 prStaRec->aucMacAddr, !prStaRec->flgTdlsIsInitiator, 0, &rHisOthers);
5685 }
5686 else
5687 {
5688 cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
5689 cnmStaRecFree(prAdapter, prStaRec, TRUE); /* release to other TDLS peers */
5690 DBGLOG(TDLS, TRACE, ("<tdls_cfg> %s: NL80211_TDLS_DISABLE_LINK\n",
5691 __FUNCTION__));
5692
5693 TDLS_LINK_DECREASE(prGlueInfo);
5694 //while(1); //sample debug
5695 }
5696
5697 /* work-around link count */
5698 if ((TDLS_LINK_COUNT(prGlueInfo) < 0) ||
5699 (TDLS_LINK_COUNT(prGlueInfo) > 1))
5700 {
5701 /* ERROR case: work-around to recount by searching all station records */
5702 UINT32 u4Idx;
5703
5704 TDLS_LINK_COUNT_RESET(prGlueInfo);
5705
5706 for(u4Idx=0; u4Idx<CFG_STA_REC_NUM; u4Idx++)
5707 {
5708 prStaRec = &prAdapter->arStaRec[u4Idx];
5709
5710 if (prStaRec->fgIsInUse &&
5711 IS_TDLS_STA(prStaRec))
5712 {
5713 TDLS_LINK_INCREASE(prGlueInfo);
5714 }
5715 }
5716
5717 if (TDLS_LINK_COUNT(prGlueInfo) > 1)
5718 {
5719 /* number of links is still > 1 */
5720 DBGLOG(TDLS, INFO, ("<tdls_cfg> %s: cTdlsLinkCnt %d > 1?\n",
5721 __FUNCTION__, TDLS_LINK_COUNT(prGlueInfo)));
5722
5723 TDLS_LINK_COUNT_RESET(prGlueInfo);
5724
5725 /* free all TDLS links */
5726 for(u4Idx=0; u4Idx<CFG_STA_REC_NUM; u4Idx++)
5727 {
5728 prStaRec = &prAdapter->arStaRec[u4Idx];
5729
5730 if (prStaRec->fgIsInUse &&
5731 IS_TDLS_STA(prStaRec))
5732 {
5733 cnmStaRecFree(prAdapter, prStaRec, TRUE);
5734 }
5735 }
5736
5737 /* maybe inform supplicant ? */
5738 }
5739 }
5740
5741 /* display TDLS link history */
5742 TdlsInfoDisplay(prAdapter, NULL, 0, NULL);
5743
5744 return TDLS_STATUS_SUCCESS;
5745 }
5746
5747
5748 /*----------------------------------------------------------------------------*/
5749 /*!
5750 * \brief This routine is called to send a TDLS action data frame.
5751 *
5752 * \param[in] prAdapter Pointer to the Adapter structure
5753 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
5754 * \param[in] u4SetBufferLen The length of the set buffer
5755 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
5756 * bytes read from the set buffer. If the call failed due to invalid length of
5757 * the set buffer, returns the amount of storage needed.
5758 *
5759 * \retval TDLS_STATUS_xx
5760 */
5761 /*----------------------------------------------------------------------------*/
5762 TDLS_STATUS
5763 TdlsexMgmtCtrl (
5764 ADAPTER_T *prAdapter,
5765 VOID *pvSetBuffer,
5766 UINT_32 u4SetBufferLen,
5767 UINT_32 *pu4SetInfoLen
5768 )
5769 {
5770 GLUE_INFO_T *prGlueInfo;
5771 TDLS_MGMT_TX_INFO *prMgmtTxInfo;
5772 STA_RECORD_T *prStaRec;
5773
5774
5775 /* sanity check */
5776 if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL))
5777 {
5778 DBGLOG(TDLS, ERROR,
5779 ("<tdls_cmd> %s: sanity fail!\n", __FUNCTION__));
5780 return TDLS_STATUS_FAILURE;
5781 }
5782
5783 /* init */
5784 prGlueInfo = (GLUE_INFO_T *)prAdapter->prGlueInfo;
5785 *pu4SetInfoLen = sizeof(TDLS_MGMT_TX_INFO);
5786 prMgmtTxInfo = (TDLS_MGMT_TX_INFO *)pvSetBuffer;
5787
5788 switch(prMgmtTxInfo->ucActionCode)
5789 {
5790 case TDLS_FRM_ACTION_DISCOVERY_RESPONSE:
5791 prStaRec = NULL;
5792 break;
5793
5794 case TDLS_FRM_ACTION_SETUP_REQ:
5795 prStaRec = cnmGetStaRecByAddress(prAdapter,
5796 (UINT_8) NETWORK_TYPE_AIS_INDEX,
5797 prMgmtTxInfo->aucPeer);
5798 if ((prStaRec != NULL) && (prStaRec->ucStaState == STA_STATE_3))
5799 {
5800 /* rekey? we reject re-setup link currently */
5801 /* TODO: Still can setup link during rekey */
5802
5803 /*
5804 return success to avoid supplicant clear TDLS entry;
5805 Or we cannot send out any TDLS tear down frame to the peer
5806 */
5807 DBGLOG(TDLS, TRACE,
5808 ("<tdls_cmd> %s: skip new setup on the exist link!\n",
5809 __FUNCTION__));
5810 return TDLS_STATUS_SUCCESS;
5811 }
5812
5813 prStaRec = NULL;
5814 break;
5815
5816 case TDLS_FRM_ACTION_SETUP_RSP:
5817 case TDLS_FRM_ACTION_CONFIRM:
5818 case TDLS_FRM_ACTION_TEARDOWN:
5819 prStaRec = cnmGetStaRecByAddress(prAdapter,
5820 (UINT_8) NETWORK_TYPE_AIS_INDEX,
5821 prMgmtTxInfo->aucPeer);
5822 #if 0 /* in some cases, the prStaRec is still NULL */
5823 /*
5824 EX: if a peer sends us a TDLS setup request with wrong BSSID,
5825 supplicant will not call TdlsexPeerAdd() to create prStaRec and
5826 supplicant will send a TDLS setup response with status code 7.
5827
5828 So in the case, prStaRec will be NULL.
5829 */
5830 if (prStaRec == NULL)
5831 {
5832 DBGLOG(TDLS, ERROR,
5833 ("<tdls_cfg> %s: cannot find the peer!\n",
5834 __FUNCTION__));
5835 return -EINVAL;
5836 }
5837 #endif
5838 break;
5839
5840 /*
5841 TODO: Discovery response frame
5842 Note that the TDLS Discovery Response frame is not a TDLS frame but a 11
5843 Public Action frame.
5844 In WiFi TDLS Tech Minutes June 8 2010.doc,
5845 a public action frame (i.e. it is no longer an encapsulated data frame)
5846 */
5847
5848 default:
5849 DBGLOG(TDLS, ERROR,
5850 ("<tdls_cfg> %s: wrong action_code %d!\n",
5851 __FUNCTION__, prMgmtTxInfo->ucActionCode));
5852 return TDLS_STATUS_FAILURE;
5853 }
5854
5855 /* send the TDLS data frame */
5856 if (prStaRec != NULL)
5857 {
5858 DBGLOG(TDLS, INFO, ("<tdls_cfg> %s: ["MACSTR"] ps=%d status=%d\n",
5859 __FUNCTION__, MAC2STR(prStaRec->aucMacAddr),
5860 prStaRec->fgIsInPS, prMgmtTxInfo->u2StatusCode));
5861
5862 if (prMgmtTxInfo->ucActionCode == TDLS_FRM_ACTION_TEARDOWN)
5863 {
5864 /* record disconnect history */
5865 TdlsLinkHistoryRecord(prGlueInfo, TRUE, prMgmtTxInfo->aucPeer,
5866 TRUE, prMgmtTxInfo->u2StatusCode, NULL);
5867 }
5868 }
5869
5870 return TdlsDataFrameSend(
5871 prAdapter,
5872 prStaRec,
5873 prMgmtTxInfo->aucPeer,
5874 prMgmtTxInfo->ucActionCode,
5875 prMgmtTxInfo->ucDialogToken,
5876 prMgmtTxInfo->u2StatusCode,
5877 (UINT_8 *)prMgmtTxInfo->aucSecBuf,
5878 prMgmtTxInfo->u4SecBufLen);
5879 }
5880
5881
5882 /*----------------------------------------------------------------------------*/
5883 /*!
5884 * \brief This routine is called to add a peer record.
5885 *
5886 * \param[in] prAdapter Pointer to the Adapter structure
5887 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
5888 * \param[in] u4SetBufferLen The length of the set buffer
5889 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
5890 * bytes read from the set buffer. If the call failed due to invalid length of
5891 * the set buffer, returns the amount of storage needed.
5892 *
5893 * \retval TDLS_STATUS_xx
5894 */
5895 /*----------------------------------------------------------------------------*/
5896 TDLS_STATUS
5897 TdlsexPeerAdd (
5898 ADAPTER_T *prAdapter,
5899 VOID *pvSetBuffer,
5900 UINT_32 u4SetBufferLen,
5901 UINT_32 *pu4SetInfoLen
5902 )
5903 {
5904 GLUE_INFO_T *prGlueInfo;
5905 TDLS_CMD_PEER_ADD_T *prCmd;
5906 BSS_INFO_T *prAisBssInfo;
5907 STA_RECORD_T *prStaRec;
5908 UINT_8 ucNonHTPhyTypeSet;
5909 UINT32 u4StartIdx;
5910 OS_SYSTIME rCurTime;
5911
5912
5913 /* sanity check */
5914 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s\n", __FUNCTION__));
5915
5916 if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL))
5917 {
5918 DBGLOG(TDLS, ERROR,
5919 ("<tdls_cmd> %s: sanity fail!\n", __FUNCTION__));
5920 return TDLS_STATUS_FAILURE;
5921 }
5922
5923 /* init */
5924 prGlueInfo = (GLUE_INFO_T *)prAdapter->prGlueInfo;
5925 *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T);
5926 prCmd = (TDLS_CMD_PEER_ADD_T *)pvSetBuffer;
5927 prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
5928 u4StartIdx = 0;
5929
5930 /* search old entry */
5931 prStaRec = cnmGetStaRecByAddress(prAdapter,
5932 (UINT_8) NETWORK_TYPE_AIS_INDEX,
5933 prCmd->aucPeerMac);
5934
5935 /* check if any TDLS link exists because we only support one TDLS link currently */
5936 if (prStaRec == NULL)
5937 {
5938 /* the MAC is new peer */
5939 prStaRec = cnmStaTheTypeGet(prAdapter, NETWORK_TYPE_AIS_INDEX,
5940 STA_TYPE_TDLS_PEER, &u4StartIdx);
5941
5942 if (prStaRec != NULL)
5943 {
5944 /* a building TDLS link exists */
5945 DBGLOG(TDLS, ERROR,
5946 ("<tdls_cmd> %s: one TDLS link setup ["MACSTR"] is going...\n",
5947 __FUNCTION__, MAC2STR(prStaRec->aucMacAddr)));
5948
5949 if (prStaRec->ucStaState != STA_STATE_3)
5950 {
5951 /* check timeout */
5952 GET_CURRENT_SYSTIME(&rCurTime);
5953
5954 if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsSetupStartTime,
5955 SEC_TO_SYSTIME(TDLS_SETUP_TIMEOUT_SEC)))
5956 {
5957 /* free the StaRec */
5958 cnmStaRecFree(prAdapter, prStaRec, TRUE);
5959
5960 DBGLOG(TDLS, ERROR,
5961 ("<tdls_cmd> %s: free going TDLS link setup ["MACSTR"]\n",
5962 __FUNCTION__, MAC2STR(prStaRec->aucMacAddr)));
5963
5964 /* handle new setup */
5965 prStaRec = NULL;
5966 }
5967 else
5968 return TDLS_STATUS_FAILURE;
5969 }
5970 else
5971 {
5972 /* the TDLS is built and works fine, reject new one */
5973 return TDLS_STATUS_FAILURE;
5974 }
5975 }
5976 }
5977 else
5978 {
5979 if (prStaRec->ucStaState == STA_STATE_3)
5980 {
5981 /* the peer exists, maybe TPK lifetime expired, supplicant wants to renew key */
5982 TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE,
5983 prStaRec->aucMacAddr, TRUE,
5984 TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL);
5985
5986 /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */
5987 cfg80211_tdls_oper_request(prAdapter->prGlueInfo->prDevHandler,
5988 prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN,
5989 TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC);
5990
5991 DBGLOG(TDLS, TRACE,
5992 ("<tdls_cmd> %s: re-setup link for ["MACSTR"] maybe re-key?\n",
5993 __FUNCTION__, MAC2STR(prStaRec->aucMacAddr)));
5994 return TDLS_STATUS_FAILURE;
5995 }
5996 }
5997
5998 /*
5999 create new entry if not exist
6000
6001 1. we are initiator
6002 (1) send TDLS setup request
6003 wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0);
6004 create a station record with STA_STATE_1.
6005 (2) got TDLS setup response and send TDLS setup confirm
6006 wpa_tdls_enable_link()
6007 update a station record with STA_STATE_3.
6008
6009 2. we are responder
6010 (1) got TDLS setup request
6011 wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0);
6012 create a station record with STA_STATE_1.
6013 (2) send TDLS setup response
6014 (3) got TDLS setup confirm
6015 wpa_tdls_enable_link()
6016 update a station record with STA_STATE_3.
6017 */
6018 if (prStaRec == NULL)
6019 {
6020 prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX);
6021
6022 if (prStaRec == NULL)
6023 {
6024 /* shall not be here */
6025 DBGLOG(TDLS, ERROR,
6026 ("<tdls_cmd> %s: alloc prStaRec fail!\n", __FUNCTION__));
6027 return TDLS_STATUS_RESOURCES;
6028 }
6029
6030 /* init the prStaRec */
6031 /* prStaRec will be zero first in cnmStaRecAlloc() */
6032 COPY_MAC_ADDR(prStaRec->aucMacAddr, prCmd->aucPeerMac);
6033
6034 // cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
6035 }
6036 else
6037 {
6038 #if 0
6039 if ((prStaRec->ucStaState > STA_STATE_1) && (IS_TDLS_STA(prStaRec)))
6040 {
6041 /*
6042 test plan: The STAUT should locally tear down existing TDLS direct link and
6043 respond with Set up Response frame.
6044 */
6045 cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
6046 }
6047 #endif
6048 }
6049
6050 /* reference to bssCreateStaRecFromBssDesc() and use our best capability */
6051 /* reference to assocBuildReAssocReqFrameCommonIEs() to fill elements */
6052
6053 /* prStaRec->u2CapInfo */
6054 /* TODO: Need to parse elements from setup request frame */
6055 prStaRec->u2OperationalRateSet = prAisBssInfo->u2OperationalRateSet;
6056 prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet;
6057 prStaRec->u2DesiredNonHTRateSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet;
6058 prStaRec->ucPhyTypeSet = prAisBssInfo->ucPhyTypeSet;
6059 prStaRec->eStaType = STA_TYPE_TDLS_PEER;
6060
6061 prStaRec->ucDesiredPhyTypeSet = /*prStaRec->ucPhyTypeSet & */
6062 prAdapter->rWifiVar.ucAvailablePhyTypeSet;
6063 ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG;
6064
6065 /* check for Target BSS's non HT Phy Types */
6066 if (ucNonHTPhyTypeSet)
6067 {
6068 if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP)
6069 {
6070 prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX;
6071 }
6072 else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM)
6073 {
6074 prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX;
6075 }
6076 else /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */
6077 {
6078 prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX;
6079 }
6080
6081 prStaRec->fgHasBasicPhyType = TRUE;
6082 }
6083 else
6084 {
6085 /* use mandatory for 11N only BSS */
6086 // ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N);
6087
6088 prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX;
6089 prStaRec->fgHasBasicPhyType = FALSE;
6090 }
6091
6092 /* update non HT Desired Rate Set */
6093 {
6094 P_CONNECTION_SETTINGS_T prConnSettings;
6095
6096 prConnSettings = &(prAdapter->rWifiVar.rConnSettings);
6097 prStaRec->u2DesiredNonHTRateSet =\
6098 (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet);
6099 }
6100
6101 #if 0 /* TdlsexPeerAdd() will be called before we receive setup rsp in TdlsexRxFrameHandle() */
6102 /* check if the add is from the same peer in the 1st unhandled setup request frame */
6103 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: ["MACSTR"] ["MACSTR"]\n",
6104 __FUNCTION__, MAC2STR(prGlueInfo->aucTdlsHtPeerMac),
6105 MAC2STR(prCmd->aucPeerMac)));
6106
6107 if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0)
6108 {
6109 /* copy the HT capability from its setup request */
6110 kalMemCopy(&prStaRec->rTdlsHtCap,
6111 &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T));
6112
6113 prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N;
6114 prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX);
6115
6116 /* reset backup */
6117 kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap));
6118 kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac));
6119
6120 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: peer is a HT device\n", __FUNCTION__));
6121 }
6122 #endif
6123
6124 /* update WMM: must support due to UAPSD in TDLS link */
6125 prStaRec->fgIsWmmSupported = TRUE;
6126 prStaRec->fgIsUapsdSupported = TRUE;
6127
6128 /* update station record to firmware */
6129 cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
6130
6131 /* update time */
6132 GET_CURRENT_SYSTIME(&prStaRec->rTdlsSetupStartTime);
6133
6134 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: create a peer ["MACSTR"]\n",
6135 __FUNCTION__, MAC2STR(prStaRec->aucMacAddr)));
6136
6137 return TDLS_STATUS_SUCCESS;
6138 }
6139
6140
6141 /*----------------------------------------------------------------------------*/
6142 /*!
6143 * \brief This routine is called to update a peer record.
6144 *
6145 * \param[in] prAdapter Pointer to the Adapter structure
6146 * \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set
6147 * \param[in] u4SetBufferLen The length of the set buffer
6148 * \param[out] pu4SetInfoLen If the call is successful, returns the number of
6149 * bytes read from the set buffer. If the call failed due to invalid length of
6150 * the set buffer, returns the amount of storage needed.
6151 *
6152 * \retval TDLS_STATUS_xx
6153 */
6154 /*----------------------------------------------------------------------------*/
6155 TDLS_STATUS
6156 TdlsexPeerUpdate (
6157 ADAPTER_T *prAdapter,
6158 VOID *pvSetBuffer,
6159 UINT_32 u4SetBufferLen,
6160 UINT_32 *pu4SetInfoLen
6161 )
6162 {
6163 GLUE_INFO_T *prGlueInfo;
6164 TDLS_CMD_PEER_UPDATE_T *prCmd;
6165 BSS_INFO_T *prAisBssInfo;
6166 STA_RECORD_T *prStaRec;
6167 IE_HT_CAP_T *prHtCap;
6168
6169
6170 /* sanity check */
6171 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s\n", __FUNCTION__));
6172
6173 if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL))
6174 {
6175 DBGLOG(TDLS, ERROR,
6176 ("<tdls_cmd> %s: sanity fail!\n", __FUNCTION__));
6177 return TDLS_STATUS_FAILURE;
6178 }
6179
6180 /* init */
6181 prGlueInfo = (GLUE_INFO_T *)prAdapter->prGlueInfo;
6182 *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T);
6183 prCmd = (TDLS_CMD_PEER_UPDATE_T *)pvSetBuffer;
6184 prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
6185
6186 /* search old entry */
6187 prStaRec = cnmGetStaRecByAddress(prAdapter,
6188 (UINT_8) NETWORK_TYPE_AIS_INDEX,
6189 prCmd->aucPeerMac);
6190
6191 /*
6192 create new entry if not exist
6193
6194 1. we are initiator
6195 (1) send TDLS setup request
6196 wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0);
6197 create a station record with STA_STATE_1.
6198 (2) got TDLS setup response and send TDLS setup confirm
6199 wpa_tdls_enable_link()
6200 update a station record with STA_STATE_3.
6201
6202 2. we are responder
6203 (1) got TDLS setup request
6204 wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0);
6205 create a station record with STA_STATE_1.
6206 (2) send TDLS setup response
6207 (3) got TDLS setup confirm
6208 wpa_tdls_enable_link()
6209 update a station record with STA_STATE_3.
6210 */
6211 if ((prStaRec == NULL) || (prStaRec->fgIsInUse == 0))
6212 {
6213 DBGLOG(TDLS, ERROR,
6214 ("<tdls_cmd> %s: cannot find the peer!\n", __FUNCTION__));
6215 return TDLS_STATUS_FAILURE;
6216 }
6217
6218 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: update a peer ["MACSTR"] %d -> %d, 0x%x\n",
6219 __FUNCTION__, MAC2STR(prStaRec->aucMacAddr),
6220 prStaRec->ucStaState, STA_STATE_3, prStaRec->eStaType));
6221
6222 if (!IS_TDLS_STA(prStaRec))
6223 {
6224 DBGLOG(TDLS, ERROR,
6225 ("<tdls_cmd> %s: peer is not TDLS one!\n", __FUNCTION__));
6226 return TDLS_STATUS_FAILURE;
6227 }
6228
6229 /* check if the add is from the same peer in the 1st unhandled setup request frame */
6230 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: ["MACSTR"] ["MACSTR"]\n",
6231 __FUNCTION__, MAC2STR(prGlueInfo->aucTdlsHtPeerMac),
6232 MAC2STR(prCmd->aucPeerMac)));
6233
6234 if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0)
6235 {
6236 /* copy the HT capability from its setup request */
6237 kalMemCopy(&prStaRec->rTdlsHtCap,
6238 &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T));
6239
6240 prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N;
6241 prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX);
6242
6243 /* reset backup */
6244 kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap));
6245 kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac));
6246
6247 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: peer is a HT device\n", __FUNCTION__));
6248 }
6249
6250 /* update the record join time. */
6251 GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime);
6252
6253 /* update Station Record - Status/Reason Code */
6254 prStaRec->u2StatusCode = prCmd->u2StatusCode;
6255
6256 /* prStaRec->ucStaState shall be STA_STATE_1 */
6257
6258 prStaRec->u2CapInfo = prCmd->u2Capability;
6259 /* prStaRec->u2OperationalRateSet */
6260 prStaRec->u2AssocId = 0; /* no use */
6261 prStaRec->u2ListenInterval = 0; /* unknown */
6262 /* prStaRec->ucDesiredPhyTypeSet */
6263 /* prStaRec->u2DesiredNonHTRateSet */
6264 /* prStaRec->u2BSSBasicRateSet */
6265 /* prStaRec->ucMcsSet */
6266 /* prStaRec->fgSupMcs32 */
6267 /* prStaRec->u2HtCapInfo */
6268 prStaRec->fgIsQoS = TRUE;
6269 prStaRec->fgIsUapsdSupported = (prCmd->UapsdBitmap == 0)?FALSE:TRUE;
6270 /* prStaRec->ucAmpduParam */
6271 /* prStaRec->u2HtExtendedCap */
6272 prStaRec->u4TxBeamformingCap = 0; /* no use */
6273 prStaRec->ucAselCap = 0; /* no use */
6274 prStaRec->ucRCPI = 0;
6275 prStaRec->ucBmpTriggerAC = prCmd->UapsdBitmap;
6276 prStaRec->ucBmpDeliveryAC = prCmd->UapsdBitmap;
6277 prStaRec->ucUapsdSp = prCmd->UapsdMaxSp;
6278
6279 /* update HT */
6280 #if (TDLS_CFG_HT_SUP == 1)
6281 if (prCmd->fgIsSupHt == FALSE)
6282 {
6283 /* no HT IE is from supplicant so we use the backup */
6284 prHtCap = (IE_HT_CAP_T *) &prStaRec->rTdlsHtCap;
6285
6286 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: ["MACSTR"] update ht ie 0x%x\n",
6287 __FUNCTION__, MAC2STR(prStaRec->aucMacAddr), prHtCap->ucId));
6288
6289 if (prHtCap->ucId == ELEM_ID_HT_CAP)
6290 {
6291 prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0];
6292 prStaRec->fgSupMcs32 =
6293 (prHtCap->rSupMcsSet.aucRxMcsBitmask[32/8] & BIT(0)) ?
6294 TRUE : FALSE;
6295
6296 prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo;
6297 prStaRec->ucAmpduParam = prHtCap->ucAmpduParam;
6298 prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap;
6299 prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap;
6300 prStaRec->ucAselCap = prHtCap->ucAselCap;
6301 prStaRec->ucDesiredPhyTypeSet |= PHY_TYPE_SET_802_11N;
6302 }
6303 }
6304 else
6305 {
6306 /* TODO: use the HT IE from supplicant */
6307 }
6308 #endif /* TDLS_CFG_HT_SUP */
6309
6310 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: UAPSD 0x%x %d MCS=0x%x\n",
6311 __FUNCTION__, prCmd->UapsdBitmap, prCmd->UapsdMaxSp,
6312 prStaRec->ucMcsSet));
6313
6314 // cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3);
6315
6316 DBGLOG(TDLS, INFO, ("<tdls_cmd> %s: update a peer ["MACSTR"]\n",
6317 __FUNCTION__, MAC2STR(prStaRec->aucMacAddr)));
6318
6319 return TDLS_STATUS_SUCCESS;
6320 }
6321
6322
6323 /*----------------------------------------------------------------------------*/
6324 /*!
6325 * \brief This routine is called to check if we need to drop a TDLS action frame.
6326 *
6327 * \param[in] *pPkt Pointer to the struct sk_buff->data.
6328 * \param[in]
6329 * \param[in]
6330 *
6331 * \retval None
6332 */
6333 /*----------------------------------------------------------------------------*/
6334 BOOLEAN
6335 TdlsexRxFrameDrop(
6336 GLUE_INFO_T *prGlueInfo,
6337 UINT_8 *pPkt
6338 )
6339 {
6340 ADAPTER_T *prAdapter;
6341 UINT8 ucActionId;
6342
6343
6344 /* sanity check */
6345 if ((pPkt == NULL) || (*(pPkt+12) != 0x89) || (*(pPkt+13) != 0x0d))
6346 return FALSE; /* not TDLS data frame htons(0x890d) */
6347
6348 #if 0 /* supplicant handles this check */
6349 if (prStaRec == NULL)
6350 return FALSE; /* shall not be here */
6351
6352 DBGLOG(TDLS, INFO,
6353 ("<tdls_fme> %s: Rcv a TDLS action frame (id=%d) %d %d\n",
6354 __FUNCTION__, *(pPkt+13+4),
6355 prStaRec->fgTdlsIsProhibited, fgIsPtiTimeoutSkip));
6356
6357 /* check if TDLS Prohibited bit is set in AP's beacon */
6358 if (prStaRec->fgTdlsIsProhibited == TRUE)
6359 return TRUE;
6360 #endif
6361
6362 ucActionId = *(pPkt+12+2+2); /* skip dst, src MAC, type, payload type, category */
6363
6364 if (fgIsPtiTimeoutSkip == TRUE)
6365 {
6366 /* also skip any tear down frame from the peer */
6367 if (ucActionId == TDLS_FRM_ACTION_TEARDOWN)
6368 return TRUE;
6369 }
6370
6371 prAdapter = prGlueInfo->prAdapter;
6372 DBGLOG(TDLS, INFO,
6373 ("<tdls_fme> %s: Rcv a TDLS action frame %d (%u)\n",
6374 __FUNCTION__, ucActionId,
6375 (UINT32)prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem));
6376
6377 if (ucActionId == TDLS_FRM_ACTION_TEARDOWN)
6378 {
6379 DBGLOG(TDLS, WARN,
6380 ("<tdls_fme> %s: Rcv a TDLS tear down frame %d, will DISABLE link\n",
6381 __FUNCTION__, *(pPkt+13+4))); /* reason code */
6382
6383 /* record disconnect history */
6384 TdlsLinkHistoryRecord(prGlueInfo, TRUE, pPkt+6, FALSE, *(pPkt+13+4), NULL);
6385
6386 /* inform tear down to supplicant only in OPEN/NONE mode */
6387 /*
6388 we need to tear down the link manually; or supplicant will display
6389 "No FTIE in TDLS Teardown" and it will not tear down the link
6390 */
6391 cfg80211_tdls_oper_request(prGlueInfo->prDevHandler,
6392 pPkt+6, TDLS_FRM_ACTION_TEARDOWN, *(pPkt+13+4), GFP_ATOMIC);
6393 }
6394
6395 #if 0 /* pass all to supplicant except same thing is handled in supplicant */
6396 if (((*(pPkt+13+3)) == TDLS_FRM_ACTION_PTI) ||
6397 ((*(pPkt+13+3)) == TDLS_FRM_ACTION_CHAN_SWITCH_REQ) ||
6398 ((*(pPkt+13+3)) == TDLS_FRM_ACTION_CHAN_SWITCH_RSP) ||
6399 ((*(pPkt+13+3)) == TDLS_FRM_ACTION_PTI_RSP))
6400 {
6401 return TRUE;
6402 }
6403 #endif
6404
6405 return FALSE;
6406 }
6407
6408
6409 /*----------------------------------------------------------------------------*/
6410 /*! \brief This routine is called to parse some IEs in the setup frame from the peer.
6411 *
6412 * \param[in] prGlueInfo Pointer to the Adapter structure
6413 * \param[in] pPkt Pointer to the ethernet packet
6414 *
6415 * \retval None
6416 *
6417 */
6418 /*----------------------------------------------------------------------------*/
6419 VOID
6420 TdlsexRxFrameHandle(
6421 GLUE_INFO_T *prGlueInfo,
6422 UINT8 *pPkt,
6423 UINT16 u2PktLen
6424 )
6425 {
6426 ADAPTER_T *prAdapter;
6427 STA_RECORD_T *prStaRec;
6428 UINT8 ucActionId;
6429 UINT8 *pucPeerMac, ucElmId, ucElmLen;
6430 INT16 s2FmeLen;
6431
6432
6433 /* sanity check */
6434 if ((prGlueInfo == NULL) || (pPkt == NULL) ||
6435 (*(pPkt+12) != 0x89) || (*(pPkt+13) != 0x0d))
6436 {
6437 return;
6438 }
6439
6440 ucActionId = *(pPkt+12+2+2); /* skip dst, src MAC, type, payload type, category */
6441
6442 if ((ucActionId != TDLS_FRM_ACTION_SETUP_REQ) &&
6443 (ucActionId != TDLS_FRM_ACTION_SETUP_RSP))
6444 {
6445 return;
6446 }
6447
6448 /* init */
6449 prAdapter = prGlueInfo->prAdapter;
6450 pucPeerMac = pPkt+6;
6451 s2FmeLen = (INT16)u2PktLen;
6452
6453 DBGLOG(TDLS, TRACE,
6454 ("<tdls_fme> %s: get a setup frame %d from "MACSTR"\n",
6455 __FUNCTION__, ucActionId, MAC2STR(pucPeerMac)));
6456
6457 if (ucActionId == TDLS_FRM_ACTION_SETUP_REQ)
6458 pPkt += 12+2+2+1+1+2; /* skip action, dialog token, capability */
6459 else
6460 pPkt += 12+2+2+1+2+1+2; /* skip action, status code, dialog token, capability */
6461
6462 /* check station record */
6463 prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter,
6464 (UINT_8)NETWORK_TYPE_AIS_INDEX, pucPeerMac);
6465
6466 if (prStaRec == NULL)
6467 {
6468 prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX);
6469
6470 if (prStaRec == NULL)
6471 {
6472 /* TODO: only one TDLS entry, need to free old one if timeout */
6473 DBGLOG(TDLS, ERROR,
6474 ("<tdls_cmd> %s: alloc prStaRec fail!\n", __FUNCTION__));
6475 return;
6476 }
6477
6478 /* init the prStaRec */
6479 /* prStaRec will be zero first in cnmStaRecAlloc() */
6480 COPY_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMac);
6481
6482 cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1);
6483 }
6484
6485 /* backup HT IE to station record */
6486 /* TODO: Maybe our TDLS only supports non-11n */
6487 while(s2FmeLen > 0)
6488 {
6489 ucElmId = *pPkt++;
6490 ucElmLen = *pPkt++;
6491
6492 switch(ucElmId)
6493 {
6494 case ELEM_ID_HT_CAP: /* 0x2d */
6495 /* backup the HT IE of 1st unhandled setup request frame */
6496 if (prGlueInfo->rTdlsHtCap.ucId == 0x00)
6497 {
6498 kalMemCopy(prGlueInfo->aucTdlsHtPeerMac, pucPeerMac, 6);
6499 kalMemCopy(&prGlueInfo->rTdlsHtCap, pPkt-2, ucElmLen+2);
6500
6501 /*
6502 cannot backup in prStaRec; or
6503
6504 1. we build a TDLS link
6505 2. peer re-sends setup req
6506 3. we backup HT cap element
6507 4. supplicant disables the link
6508 5. we clear the prStaRec
6509 */
6510
6511 DBGLOG(TDLS, TRACE,
6512 ("<tdls_fme> %s: "MACSTR": find a HT IE\n",
6513 __FUNCTION__, MAC2STR(pucPeerMac)));
6514 }
6515 return;
6516
6517 case ELEM_ID_EXTENDED_CAP:
6518 /* TODO: backup the extended capability IE */
6519 break;
6520 }
6521
6522 pPkt += ucElmLen;
6523 s2FmeLen -= (2+ucElmLen);
6524 }
6525 }
6526
6527
6528 /*----------------------------------------------------------------------------*/
6529 /*! \brief This routine is called to get the TDLS station record.
6530 *
6531 * \param[in] prGlueInfo Pointer to the Adapter structure
6532 * \param[in] prInBuf A pointer to the command string buffer
6533 * \param[in] u4InBufLen The length of the buffer
6534 * \param[out] None
6535 *
6536 * \retval TDLS_STATUS_SUCCESS: this is TDLS packet
6537 * TDLS_STATUS_FAILURE: this is not TDLS packet
6538 */
6539 /*----------------------------------------------------------------------------*/
6540 TDLS_STATUS
6541 TdlsexStaRecIdxGet(
6542 ADAPTER_T *prAdapter,
6543 MSDU_INFO_T *prMsduInfo
6544 )
6545 {
6546 BSS_INFO_T *prBssInfo;
6547 STA_RECORD_T *prStaRec;
6548 TDLS_STATUS Status;
6549
6550
6551 /* sanity check */
6552 if (prAdapter->prGlueInfo == NULL)
6553 return TDLS_STATUS_FAILURE;
6554 if (TDLS_IS_NO_LINK_GOING(prAdapter->prGlueInfo))
6555 return TDLS_STATUS_FAILURE;
6556
6557 if ((prAdapter == NULL) || (prMsduInfo == NULL))
6558 return TDLS_STATUS_FAILURE;
6559
6560 /* init */
6561 prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND;
6562 Status = TDLS_STATUS_SUCCESS;
6563
6564 /* get record by ether dest */
6565 prStaRec = cnmGetStaRecByAddress(prAdapter,
6566 (UINT_8) NETWORK_TYPE_AIS_INDEX,
6567 prMsduInfo->aucEthDestAddr);
6568
6569 /*
6570 TDLS Setup Request frames, TDLS Setup Response frames and TDLS Setup Confirm
6571 frames shall be transmitted through the AP and shall not be transmitted to a group
6572 address.
6573
6574 1. In first time, prStaRec == NULL or prStaRec->ucStaState != STA_STATE_3,
6575 we will send them to AP;
6576 2. When link is still on, if you command to send TDLS setup from supplicant,
6577 supplicant will DISABLE LINK first, prStaRec will be NULL then send TDLS
6578 setup frame to the peer.
6579 */
6580
6581 do {
6582 if ((prStaRec != NULL) &&
6583 (prStaRec->ucStaState == STA_STATE_3) &&
6584 (IS_TDLS_STA(prStaRec)))
6585 {
6586 /*
6587 TDLS Test Case 5.3 Tear Down
6588 Automatically sends TDLS Teardown frame to STA 2 via AP
6589
6590 11.21.5 TDLS Direct Link Teardown
6591 The TDLS Teardown frame shall be sent over the direct path and the reason
6592 code shall be set to "TDLS 40 direct link teardown for unspecified reason",
6593 except when the TDLS peer STA is unreachable via the TDLS direct link,
6594 in which case, the TDLS Teardown frame shall be sent through the AP and
6595 the reason code shall be set to "TDLS direct link teardown due to TDLS peer
6596 STA unreachable via the TDLS direct link".
6597 */
6598 // if (prStaRec->fgIsInPS == TRUE)
6599 {
6600 /*
6601 check if the packet is tear down:
6602 we do not want to use PTI to indicate the tear down and
6603 we want to send the tear down to AP then AP help us to send it
6604 */
6605 struct sk_buff *prSkb;
6606 UINT8 *pEth;
6607 UINT_16 u2EtherTypeLen;
6608
6609 prSkb = (struct sk_buff *) prMsduInfo->prPacket;
6610 if (prSkb != NULL)
6611 {
6612 UINT8 ucActionCode, ucReasonCode;
6613
6614 /* init */
6615 pEth = prSkb->data;
6616 u2EtherTypeLen = (pEth[ETH_TYPE_LEN_OFFSET] << 8) |\
6617 (pEth[ETH_TYPE_LEN_OFFSET + 1]);
6618 ucActionCode = pEth[ETH_TYPE_LEN_OFFSET+1+3];
6619 ucReasonCode = pEth[ETH_TYPE_LEN_OFFSET+1+4] |\
6620 (pEth[ETH_TYPE_LEN_OFFSET+1+5] << 8);
6621
6622 /* TDLS_REASON_CODE_UNREACHABLE: keep alive fail or PTI timeout */
6623 if ((u2EtherTypeLen == TDLS_FRM_PROT_TYPE) &&
6624 (ucActionCode == TDLS_FRM_ACTION_TEARDOWN) &&
6625 (ucReasonCode == TDLS_REASON_CODE_UNREACHABLE))
6626 {
6627 /*
6628 when we cannot reach the peer,
6629 we need AP's help to send the tear down frame
6630 */
6631 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[\
6632 NETWORK_TYPE_AIS_INDEX]);
6633 prStaRec = prBssInfo->prStaRecOfAP;
6634 if (prStaRec == NULL)
6635 {
6636 Status = TDLS_STATUS_FAILURE;
6637 break;
6638 }
6639
6640 #if 0
6641 /* change status code */
6642 pEth[ETH_TYPE_LEN_OFFSET+1+4] = \
6643 TDLS_REASON_CODE_UNREACHABLE;
6644 #endif
6645 }
6646 }
6647 }
6648
6649 prMsduInfo->ucStaRecIndex = prStaRec->ucIndex;
6650 }
6651 } while(FALSE);
6652
6653 DBGLOG(TDLS, INFO, ("<tdls> %s: (Status=%x) ["MACSTR"] ucStaRecIndex = %d!\n",
6654 __FUNCTION__, (INT32)Status, MAC2STR(prMsduInfo->aucEthDestAddr),
6655 prMsduInfo->ucStaRecIndex));
6656 return Status;
6657 }
6658
6659
6660 /*----------------------------------------------------------------------------*/
6661 /*!
6662 * @brief This function is used to check if we suffer timeout for TX quota empty case.
6663 *
6664 * \param[in] prAdapter Pointer to the Adapter structure
6665 *
6666 * @return (none)
6667 */
6668 /*----------------------------------------------------------------------------*/
6669 VOID
6670 TdlsexTxQuotaCheck(
6671 GLUE_INFO_T *prGlueInfo,
6672 STA_RECORD_T *prStaRec,
6673 UINT8 FreeQuota
6674 )
6675 {
6676 OS_SYSTIME rCurTime;
6677
6678
6679 /* sanity check */
6680 if (!IS_TDLS_STA(prStaRec))
6681 return;
6682
6683 if (FreeQuota != 0)
6684 {
6685 /* reset timeout */
6686 prStaRec->rTdlsTxQuotaEmptyTime = 0;
6687 return;
6688 }
6689
6690 /* work-around: check if the no free quota case is too long */
6691 GET_CURRENT_SYSTIME(&rCurTime);
6692
6693 if (prStaRec->rTdlsTxQuotaEmptyTime == 0)
6694 {
6695 prStaRec->rTdlsTxQuotaEmptyTime = rCurTime;
6696 }
6697 else
6698 {
6699 if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsTxQuotaEmptyTime,
6700 SEC_TO_SYSTIME(TDLS_TX_QUOTA_EMPTY_TIMEOUT)))
6701 {
6702 /* tear down the link */
6703 DBGLOG(TDLS, WARN,
6704 ("<tdls> %s: ["MACSTR"] TX quota empty timeout!\n",
6705 __FUNCTION__, MAC2STR(prStaRec->aucMacAddr)));
6706
6707 /* record disconnect history */
6708 TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr,
6709 TRUE, TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY, NULL);
6710
6711 /* inform tear down to supplicant only in OPEN/NONE mode */
6712 /*
6713 we need to tear down the link manually; or supplicant will display
6714 "No FTIE in TDLS Teardown" and it will not tear down the link
6715 */
6716 cfg80211_tdls_oper_request(prGlueInfo->prDevHandler,
6717 prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN,
6718 TDLS_REASON_CODE_UNREACHABLE, GFP_ATOMIC);
6719 }
6720 }
6721 }
6722
6723
6724 /*----------------------------------------------------------------------------*/
6725 /*!
6726 * @brief This function is used to un-initialize variables in TDLS.
6727 *
6728 * \param[in] prAdapter Pointer to the Adapter structure
6729 *
6730 * @return (none)
6731 */
6732 /*----------------------------------------------------------------------------*/
6733 VOID
6734 TdlsexUninit (
6735 ADAPTER_T *prAdapter
6736 )
6737 {
6738 #if TDLS_CFG_CMD_TEST
6739 cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend);
6740 #endif /* TDLS_CFG_CMD_TEST */
6741 }
6742
6743
6744 #endif /* CFG_SUPPORT_TDLS */
6745
6746 /* End of tdls.c */
6747